二分匹配之最大权值匹配算法---KM模板

百科:http://baike.baidu.com/link?url=vbM3H4XmfrsWfP-epdlR2sVKSNzOq4hXnWDqm5uo8fd7VWsF2SmhDV35XyVUDvVjvrtf42RUITJuNCHn-7_x6K

大神总结:http://www.cnblogs.com/skyming/archive/2012/02/18/2356919.html

代码:

 1 #include<stdio.h>
 2 #include<string.h>
 3 const int N=555,INF=0x3f3f3f3f;
 4 int lx[N],ly[N],vx[N],vy[N],slack[N],match[N];
 5 int a[N][N];
 6 int nx,ny;
 7 int dfs(int u)
 8 {
 9     vx[u]=1;
10     for(int i=1;i<=ny;i++)
11     {
12         if(vy[i])    continue;
13         int t=lx[u]+ly[i]-a[u][i];
14         if(t==0)
15         {
16             vy[i]=1;
17             if(match[i]==-1||dfs(match[i]))
18             {
19                 match[i]=u;
20                 return 1;
21             }
22         }
23         else if(slack[i]>t)
24             slack[i]=t;
25     }
26     return 0;
27 }
28 int KM()
29 {
30     int i,j,d;
31     memset(ly,0,sizeof(ly));
32     memset(match,-1,sizeof(match));
33     for(i=1,lx[i]=-INF;i<=nx;i++)
34         for(j=1;j<=ny;j++)
35             if(a[i][j]>lx[i])
36                 lx[i]=a[i][j];
37     for(i=1;i<=nx;i++)
38     {
39         memset(slack,0x3f,sizeof(slack));
40         while(1)
41         {
42             memset(vx,0,sizeof(vx));
43             memset(vy,0,sizeof(vy));
44             if(dfs(i))    break;
45             d=INF;
46             for(j=1;j<=ny;j++)
47                 if(!vy[j]&&slack[j]<d)
48                     d=slack[j];
49             //if(d==INF)    break;//该点找不到任何匹配 
50             for(j=1;j<=nx;j++)
51                 if(vx[j])
52                     lx[j]-=d;
53             for(j=1;j<=ny;j++)
54             {
55                 if(vy[j])
56                     ly[j]+=d;
57                 else
58                     slack[j]-=d;
59             }
60         }
61     }
62     int ans=0,sum=0;
63     for(i=1;i<=ny;i++)
64         if(match[i]>-1&&a[match[i]][i])
65             ans+=a[match[i]][i],sum++; 
66     printf("%d++\n",sum);//匹配数 
67     return ans;
68 }
69 int main()
70 {
71     int m,u,v,w,n,i;
72     scanf("%d",&nx);
73     scanf("%d",&ny);
74     scanf("%d",&m);
75     memset(a,0,sizeof(a));
76     while(m--)
77     {
78         scanf("%d%d%d",&u,&v,&w);
79         a[u][v]=a[v][u]=w;
80     }
81     printf("%d\n",KM());
82     return 0;
83 }

 

转载于:https://www.cnblogs.com/L-King/p/5519927.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值