题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2426
思路:就是求最大权匹配,不过一开始map应初始化为inf,然后输入遇到负边的情况就continue。。。
这样最后只需对map[match[i]][i]!=inf的计数,若不等于N,则输出-1,否则,输出ans.
View Code
1 #include<iostream> 2 const int MAXN=507; 3 const int inf=100000000; 4 using namespace std; 5 int ans; 6 int N,M,E; 7 int map[MAXN][MAXN]; 8 int lx[MAXN],ly[MAXN]; 9 int match[MAXN]; 10 bool visitx[MAXN],visity[MAXN]; 11 12 //匈牙利算法 13 int Hungary(int u){ 14 visitx[u]=true; 15 for(int i=0;i<M;i++){ 16 if(!visity[i]&&lx[u]+ly[i]==map[u][i]){ 17 visity[i]=true; 18 if(match[i]==-1||Hungary(match[i])){ 19 match[i]=u; 20 return true; 21 } 22 } 23 } 24 return false; 25 } 26 27 int KM_prefect_match(){ 28 int tmp; 29 memset(lx,0,sizeof(lx));//初始化顶标 30 memset(ly,0,sizeof(ly)); 31 for(int i=0;i<N;i++){ 32 for(int j=0;j<M;j++){ 33 lx[i]=max(lx[i],map[i][j]);//计算边权最大值 34 } 35 } 36 for(int i=0;i<N;i++) 37 { 38 while(1){ 39 memset(visitx,false,sizeof(visitx)); 40 memset(visity,false,sizeof(visity)); 41 if(Hungary(i))//匹配成功 42 break; 43 else { 44 //匹配失败,找最小值 45 tmp=inf; 46 for(int j=0;j<N;j++)if(visitx[j]){ //x在交错树中 47 for(int k=0;k<M;k++){ 48 if(!visity[k]&&tmp>lx[j]+ly[k]-map[j][k]){ //y不在交错树中 49 tmp=lx[j]+ly[k]-map[j][k]; 50 } 51 } 52 } 53 //更新顶标 54 for(int j=0;j<N;j++){ 55 if(visitx[j]) 56 lx[j]-=tmp; 57 } 58 for(int j=0;j<M;j++){ 59 if(visity[j]) 60 ly[j]+=tmp; 61 } 62 } 63 } 64 } 65 int count=0; 66 for(int i=0;i<M;i++){ 67 //对map[match[i]][i]!=inf计数 68 if(match[i]!=-1&&map[match[i]][i]!=-inf){ 69 ans+=map[match[i]][i]; 70 count++; 71 } 72 } 73 if(count==N)return true; 74 return false; 75 } 76 77 int main(){ 78 int _case=1; 79 while(~scanf("%d%d%d",&N,&M,&E)){ 80 ans=0; 81 for(int i=0;i<N;i++){ 82 for(int j=0;j<M;j++){ 83 map[i][j]=-inf; 84 } 85 } 86 memset(match,-1,sizeof(match)); 87 for(int i=1;i<=E;i++){ 88 int x,y,value; 89 scanf("%d%d%d",&x,&y,&value); 90 if(value>=0) 91 map[x][y]=value; 92 } 93 printf("Case %d: ",_case++); 94 if(KM_prefect_match()){ 95 printf("%d\n",ans); 96 }else { 97 printf("-1\n"); 98 } 99 } 100 return 0; 101 }