POJ2195-Going Home

传送门

题目大意:给定一些人和一些房子,人和房子一样多,求配对。配对代价就是人和房子的距离

思路:这是一个二分图的模型,带权二分图用KM算法即可

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<queue>
  6 #define MAXN 105
  7 #define pii pair<int,int>
  8 #define INF 0x7f7f7f7f
  9 using namespace std;
 10 int X,Y;
 11 int n;
 12 int G[MAXN][MAXN];
 13 char s[MAXN][MAXN];
 14 vector<pii> va,vb;
 15 int a[MAXN][MAXN];
 16 int b[MAXN][MAXN];
 17 int d[5]={0,1,0,-1,0};
 18 int bfs(int t){
 19     memset(b,0,sizeof(b));
 20     queue<pair<pii,int> > q;
 21     q.push(make_pair(va[t-1],0));
 22     b[va[t-1].first][va[t-1].second]=1;
 23     while(!q.empty()){
 24         int x=q.front().first.first,y=q.front().first.second;
 25         int L=q.front().second;
 26         q.pop();
 27         for(int k=0;k<4;k++){
 28             int dx=x+d[k],dy=y+d[k+1];
 29             if(1<=dx&&dx<=X&&1<=dy&&dy<=Y&&!b[dx][dy]){
 30                 b[dx][dy]=L+1;
 31                 q.push(make_pair(make_pair(dx,dy),L+1));
 32                 if(a[dx][dy]){
 33                     G[t][a[dx][dy]]=-(L+1);
 34                 }    
 35             }
 36         }
 37     }     
 38 }
 39 void init(){
 40     memset(G,0,sizeof(G));
 41     memset(a,0,sizeof(a));
 42     va.clear();
 43     vb.clear();
 44     n=0;
 45     for(int i=1;i<=X;i++){
 46         scanf("%s",s[i]+1);
 47         for(int j=1;j<=Y;j++){
 48             if('m'==s[i][j]){
 49                 va.push_back(make_pair(i,j));
 50                 n++;
 51             }
 52             else if('H'==s[i][j]){
 53                 vb.push_back(make_pair(i,j));
 54                 a[i][j]=vb.size();
 55             }
 56         }    
 57     }    
 58     for(int i=1;i<=n;i++){
 59         bfs(i);
 60     }    
 61 }
 62 int vis_v1[MAXN],vis_v2[MAXN];
 63 int ex_v1[MAXN],ex_v2[MAXN];
 64 int match[MAXN],slack[MAXN];
 65 int dfs(int x){
 66     vis_v2[x]=1;
 67     for(int i=1;i<=n;i++){
 68         if(vis_v1[i]){
 69             continue;
 70         }
 71         int gap=ex_v1[i]+ex_v2[x]-G[x][i];
 72         if(!gap){
 73             vis_v1[i]=1;
 74             if(!match[i]||dfs(match[i])){
 75                 match[i]=x;
 76                 return 1;
 77             }
 78         }
 79         else{
 80             slack[i]=min(slack[i],gap);
 81         }
 82     }    
 83     return 0;
 84 }
 85 int KM(){
 86     memset(match,0,sizeof(match));
 87     memset(ex_v1,0,sizeof(ex_v1));
 88     for(int i=1;i<=n;i++){
 89         ex_v2[i]=G[i][1];
 90         for(int j=2;j<=n;j++){
 91             ex_v2[i]=max(ex_v2[i],G[i][j]);
 92         }    
 93     }
 94     for(int i=1;i<=n;i++){
 95         memset(slack,0x7f,sizeof(slack));
 96         while(1){
 97             memset(vis_v1,0,sizeof(vis_v1));
 98             memset(vis_v2,0,sizeof(vis_v2));
 99 
100             if(dfs(i)) break;
101 
102             int d=INF;
103             for(int j=1;j<=n;j++){
104                 if(!vis_v1[j]){//!!!
105                     d=min(d,slack[j]);
106                 }
107             }
108             for(int j=1;j<=n;j++){
109                 if(vis_v2[j]){
110                     ex_v2[j]-=d;
111                 }
112                 if(vis_v1[j]){
113                     ex_v1[j]+=d;
114                 }
115                 else{
116                     slack[j]-=d;
117                 }
118             }
119         }
120     }    
121     int ans=0;
122     for(int i=1;i<=n;i++){
123         ans-=G[match[i]][i];
124     }
125     return ans;
126 }
127 void solve(){
128     printf("%d
",KM());
129 }
130 int main()
131 {
132 //    freopen("data.in","r",stdin);
133     while(1){
134         scanf("%d%d",&X,&Y);
135         if(!X&&!Y){
136             break;
137         }
138         init();
139         solve();
140     }    
141     return 0;
142 }
原文地址:https://www.cnblogs.com/w-h-h/p/7800909.html