【LA4043 训练指南】蚂蚁 【二分图最佳完美匹配,费用流】

题意ios

  给出n个白点和n个黑点的坐标,要求用n条不相交的线段把他们链接起来,其中每条线段刚好链接一个白点和一个黑点,每一个点刚好链接一条线段。ide

分析this

  结点分黑白,很容易想到二分图。其中每一个白点对应一个X结点,每一个黑点对应一个Y点,每一个黑点和每一个白点相连,权值等于两者的欧几里得距离,建模以后,最佳完美匹配就是问题的解。spa

  为何用费用流而不用KM呢,由于我不会···code

  

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <iostream>
 5 #include <vector>
 6 #include <queue>
 7 #include <cmath>
 8 
 9 using namespace std;  10 const int maxN=300;  11 const int maxm=30000+10;  12 const int INF=2147480000;  13 int n;  14 int ax[maxN],bx[maxN],ay[maxN],by[maxN];  15 
 16 struct MCMF{  17     int head[maxN],to[maxm],Next[maxm],from[maxm],flow[maxm],cap[maxm];  18     double cost[maxm];  19     int n,m,s,t,sz;  20     int inq[maxN];  21     double d[maxN];  22     int p[maxN];  23     int a[maxN];  24 
 25     void init(int n){  26         this->n=n;  27         sz=-1;  28         memset(head,-1,sizeof(head));  29  }  30     void AddEdge(int a,int b,int ca,double co){  31         ++sz;  32         to[sz]=b,from[sz]=a,Next[sz]=head[a],head[a]=sz;  33         flow[sz]=0,cap[sz]=ca,cost[sz]=co;  34         ++sz;  35         to[sz]=a,from[sz]=b,Next[sz]=head[b],head[b]=sz;  36         flow[sz]=ca,cap[sz]=ca,cost[sz]=-co;  37  }  38     bool BellmanFord(int s,int t,int &Flow,double &Cost){  39         for(int i=0;i<=n;i++)d[i]=INF;  40         memset(inq,0,sizeof(inq));  41         d[s]=0;inq[s]=1;p[s]=-1;a[s]=INF;  42         queue<int>Q;  43  Q.push(s);  44         while(!Q.empty()){  45             int u=Q.front();Q.pop();  46             inq[u]=0;  47             for(int i=head[u];i!=-1;i=Next[i]){  48                 int v=to[i];  49                 if(cap[i]>flow[i]&&d[v]>d[u]+cost[i]){  50                     d[v]=d[u]+cost[i];  51                     p[v]=i;  52                     a[v]=min(a[u],cap[i]-flow[i]);  53                     if(!inq[v]){  54  Q.push(v);  55                         inq[v]=1;  56  }  57  }  58  }  59  }  60         if(d[t]==INF)return false;  61         Flow+=a[t];  62         Cost+=d[t]*(double)a[t];  63         int u=t;  64 
 65         while(u!=s){  66             flow[p[u]]+=a[t];  67             flow[p[u]^1]-=a[t];  68             u=from[p[u]];  69  }  70         return true;  71  }  72 
 73     double Mincost(int s,int t){  74         int Flow=0;  75         double Cost=0;  76         while(BellmanFord(s,t,Flow,Cost));  77         return Cost;  78  }  79 }mcmf;  80 
 81 double dist(int X,int Y){  82     return sqrt((double)(ax[X]-bx[Y])*(ax[X]-bx[Y])+(double)(ay[X]-by[Y])*(ay[X]-by[Y]));  83 }  84 int main(){  85     while(scanf("%d",&n)!=EOF){  86         for(int i=1;i<=n;i++)  87             scanf("%d%d",&ax[i],&ay[i]);  88         for(int i=1;i<=n;i++)  89             scanf("%d%d",&bx[i],&by[i]);  90         mcmf.init(2*n+2);  91         for(int i=1;i<=n;i++)  92             mcmf.AddEdge(0,i,1,0);  93         for(int i=1;i<=n;i++)  94             mcmf.AddEdge(i+n,2*n+1,1,0);  95         for(int i=1;i<=n;i++){  96             for(int j=1;j<=n;j++){  97                 mcmf.AddEdge(i,j+n,1,dist(i,j));  98  }  99  } 100         mcmf.Mincost(0,2*n+1); 101         for(int i=1;i<=n;i++){ 102             for(int j=mcmf.head[i];j!=-1;j=mcmf.Next[j]){ 103                 if(j%2)continue; 104                 int v=mcmf.to[j]; 105                 if(mcmf.cap[j]==mcmf.flow[j]){ 106                     printf("%d\n",v-n); 107                     break; 108  } 109  } 110  } 111  } 112     return 0; 113 }
View Code
相关文章
相关标签/搜索