hdu 2426 Interesting Housing Problem 最大权匹配KM算法
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2426
Suppose that there are N students and M rooms. Each student is asked to rate some rooms (not necessarily all M rooms) by stating how he/she likes the room. The rating can be represented as an integer, positive value meaning that the student consider the room to be of good quality, zero indicating neutral, or negative implying that the student does not like living in the room. Note that you can never assign a student to a room which he/she has not rated, as the absence of rating indicates that the student cannot live in the room for other reasons.
With limited information available, you‘ve decided to simply find an assignment such that every student is assigned to a room he/she has rated, no two students are assigned to the same room, and the sum of rating is maximized while satisfying Peterson‘s requirement. The question is … what exactly is the answer?
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=500+10; 10 11 int n,m; 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++) if (w[x][y]!=-1) 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 int KM() 37 { 38 memset(link,-1,sizeof(link)); 39 memset(ly,0,sizeof(ly)); 40 for (int x=1 ;x<=n ;x++) 41 { 42 lx[x]=-inf; 43 for (int y=1 ;y<=m ;y++) 44 lx[x]=max(lx[x],w[x][y]); 45 } 46 for (int x=1 ;x<=n ;x++) 47 { 48 for (int i=1 ;i<=m ;i++) slack[i]=inf; 49 int flag=0; 50 for (int i=1 ;i<=m ;i++) if (w[x][i]!=-1) flag=1; 51 while (flag) 52 { 53 memset(visx,0,sizeof(visx)); 54 memset(visy,0,sizeof(visy)); 55 if (dfs(x)) break; 56 int d=inf; 57 for (int i=1 ;i<=m ;i++) 58 if (!visy[i] && d>slack[i]) d=slack[i]; 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; 69 int vis[maxn]; 70 memset(vis,0,sizeof(vis)); 71 for (int i=1 ;i<=m ;i++) 72 { 73 if (link[i]!=-1) 74 { 75 ans += w[link[i] ][i]; 76 vis[link[i] ]=1; 77 } 78 } 79 int i=1; 80 for (i=1 ;i<=n ;i++) 81 if (vis[i]==0) return -1; 82 return ans; 83 } 84 85 int main() 86 { 87 int e; 88 int ncase=1; 89 while (scanf("%d%d%d",&n,&m,&e)!=EOF) 90 { 91 memset(w,-1,sizeof(w)); 92 int a,b,c; 93 for (int i=0 ;i<e ;i++) 94 { 95 scanf("%d%d%d",&a,&b,&c); 96 a++ ;b++ ; 97 if (c>=0) w[a][b]=c; 98 } 99 printf("Case %d: %d\n",ncase++,KM()); 100 } 101 return 0; 102 }
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。