标签:
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2853
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<cmath> 6 #include<algorithm> 7 #define inf 0x7fffffff 8 using namespace std; 9 const int maxn=55; 10 11 int n,m,k,sum; 12 int lx[maxn],ly[maxn],visx[maxn],visy[maxn]; 13 int link[maxn],slack[maxn],w[maxn][maxn]; 14 int vis[maxn][maxn]; 15 16 int dfs(int x) 17 { 18 visx[x]=1; 19 for (int y=1 ;y<=m ;y++) 20 { 21 if (visy[y]) continue; 22 int t=lx[x]+ly[y]-w[x][y]; 23 if (t==0) 24 { 25 visy[y]=1; 26 if (link[y]==-1 || dfs(link[y])) 27 { 28 link[y]=x; 29 return 1; 30 } 31 } 32 else if (slack[y]>t) slack[y]=t; 33 } 34 return 0; 35 } 36 37 void KM() 38 { 39 memset(link,-1,sizeof(link)); 40 memset(ly,0,sizeof(ly)); 41 for (int i=1 ;i<=n ;i++) 42 { 43 lx[i]=-inf; 44 for (int j=1 ;j<=m ;j++) 45 lx[i]=max(lx[i],w[i][j]); 46 } 47 for (int x=1 ;x<=n ;x++) 48 { 49 for (int i=1 ;i<=m ;i++) slack[i]=inf; 50 while (1) 51 { 52 memset(visx,0,sizeof(visx)); 53 memset(visy,0,sizeof(visy)); 54 if (dfs(x)) break; 55 int d=inf; 56 for (int i=1 ;i<=m ;i++) 57 { 58 if (!visy[i] && slack[i]<d) d=slack[i]; 59 } 60 for (int i=1 ;i<=n ;i++) 61 if (visx[i]) lx[i] -= d; 62 for (int i=1 ;i<=m ;i++) 63 { 64 if (visy[i]) ly[i] += d; 65 else slack[i] -= d; 66 } 67 } 68 } 69 int ans=0,cnt=0; 70 for (int i=1 ;i<=m ;i++) 71 { 72 if (link[i]!=-1) 73 { 74 ans += w[link[i] ][i]; 75 if (vis[link[i] ][i]) cnt++; 76 } 77 } 78 printf("%d %d\n",n-cnt,ans-sum-cnt); 79 // for (int i=1 ;i<=m ;i++) 80 // { 81 // if (link[i]!=-1) ans += w[link[i] ][i]; 82 // } 83 // printf("%d %d\n",n-ans%k,ans/k-sum); 84 } 85 86 int main() 87 { 88 while (scanf("%d%d",&n,&m)!=EOF) 89 { 90 memset(w,0,sizeof(w)); 91 memset(vis,0,sizeof(vis)); 92 k=200; 93 for (int i=1 ;i<=n ;i++) 94 { 95 for (int j=1 ;j<=m ;j++) 96 { 97 scanf("%d",&w[i][j]); 98 /// w[i][j] *= k; 99 } 100 } 101 int a; 102 sum=0; 103 for (int i=1 ;i<=n ;i++) 104 { 105 scanf("%d",&a); 106 sum += w[i][a]; 107 ///sum += w[i][a]/k; 108 w[i][a] ++ ; 109 vis[i][a]=1; 110 } 111 KM(); 112 } 113 return 0; 114 }
方法二:和方法一的区别就在于对每条边都乘以k(比如k=200),对于原有匹配w[x][y]++,最后的答案最大效率为ans。
那么差值=ans/k-sum;个数=n-ans%k。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<cmath> 6 #include<algorithm> 7 #define inf 0x7fffffff 8 using namespace std; 9 const int maxn=55; 10 11 int n,m,k,sum; 12 int lx[maxn],ly[maxn],visx[maxn],visy[maxn]; 13 int link[maxn],slack[maxn],w[maxn][maxn]; 14 15 int dfs(int x) 16 { 17 visx[x]=1; 18 for (int y=1 ;y<=m ;y++) 19 { 20 if (visy[y]) continue; 21 int t=lx[x]+ly[y]-w[x][y]; 22 if (t==0) 23 { 24 visy[y]=1; 25 if (link[y]==-1 || dfs(link[y])) 26 { 27 link[y]=x; 28 return 1; 29 } 30 } 31 else if (slack[y]>t) slack[y]=t; 32 } 33 return 0; 34 } 35 36 void KM() 37 { 38 memset(link,-1,sizeof(link)); 39 memset(ly,0,sizeof(ly)); 40 for (int i=1 ;i<=n ;i++) 41 { 42 lx[i]=-inf; 43 for (int j=1 ;j<=m ;j++) 44 lx[i]=max(lx[i],w[i][j]); 45 } 46 for (int x=1 ;x<=n ;x++) 47 { 48 for (int i=1 ;i<=m ;i++) slack[i]=inf; 49 while (1) 50 { 51 memset(visx,0,sizeof(visx)); 52 memset(visy,0,sizeof(visy)); 53 if (dfs(x)) break; 54 int d=inf; 55 for (int i=1 ;i<=m ;i++) 56 { 57 if (!visy[i] && slack[i]<d) d=slack[i]; 58 } 59 for (int i=1 ;i<=n ;i++) 60 if (visx[i]) lx[i] -= d; 61 for (int i=1 ;i<=m ;i++) 62 { 63 if (visy[i]) ly[i] += d; 64 else slack[i] -= d; 65 } 66 } 67 } 68 int ans=0,cnt=0; 69 for (int i=1 ;i<=m ;i++) 70 { 71 if (link[i]!=-1) ans += w[link[i] ][i]; 72 } 73 printf("%d %d\n",n-ans%k,ans/k-sum); 74 } 75 76 int main() 77 { 78 while (scanf("%d%d",&n,&m)!=EOF) 79 { 80 memset(w,0,sizeof(w)); 81 k=200; 82 for (int i=1 ;i<=n ;i++) 83 { 84 for (int j=1 ;j<=m ;j++) 85 { 86 scanf("%d",&w[i][j]); 87 w[i][j] *= k; 88 } 89 } 90 int a; 91 sum=0; 92 for (int i=1 ;i<=n ;i++) 93 { 94 scanf("%d",&a); 95 sum += w[i][a]/k; 96 w[i][a] ++ ; 97 } 98 KM(); 99 } 100 return 0; 101 }
标签:
原文地址:http://www.cnblogs.com/huangxf/p/4339786.html