【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
相關文章
相關標籤/搜索