P3967 [TJOI2014]匹配 KM算法

这道题首先要实现KM算法求出权值;

然后要求我们计算出所有的完美匹配中的交集,也就是说,必须出现在完美匹配当中的男女朋友关系

所以要求出交集,我们可以采用暴力的方式

  由于KM算法(我用的是优化后的模板 0(n^3))题目给出的范围也就80,所以多一层暴力也不会超时

  所以我们把第一次匹配中存在的男女生配偶数组再copy到另一个数组sto【】当中

  然后将每一组中的权值置为0,再算KM算法,假如总值不变,则证明不在交集当中,变小就证明在。

    变大呢?对不起,不可能变大的

然后最后排序输出就好

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 //Data
 4 typedef long long ll;
 5 const int N=500;
 6 const int inf=0x3f3f3f3f;
 7 int n,m,e[N+7][N+7];
 8 int sto[N];
 9 //KM
10 int mb[N+7],vb[N+7],ka[N+7],kb[N+7],p[N+7],c[N+7];
11 int qf,qb;
12 struct node
13 {
14     int l,r;
15 }last[N];
16 void Bfs(int u){
17     int a,v=0,vl=0,d;
18     for(int i=1;i<=n;i++) p[i]=0,c[i]=inf;
19     mb[v]=u;
20     do {
21         a=mb[v],d=inf,vb[v]=1;
22         for(int b=1;b<=n;b++)if(!vb[b]){
23             if(c[b]>ka[a]+kb[b]-e[a][b])
24                 c[b]=ka[a]+kb[b]-e[a][b],p[b]=v;
25             if(c[b]<d) d=c[b],vl=b;
26         }
27         for(int b=0;b<=n;b++)
28             if(vb[b]) ka[mb[b]]-=d,kb[b]+=d;
29             else c[b]-=d;
30         v=vl;
31     } while(mb[v]);
32     while(v) mb[v]=mb[p[v]],v=p[v];
33 }
34 ll KM()
35 {
36     for(int i=1;i<=n;i++)
37         mb[i]=ka[i]=kb[i]=0;
38     for(int a=1;a<=n;a++){
39         for(int b=1;b<=n;b++)
40             vb[b]=0;
41         Bfs(a);
42     }
43     ll res=0;
44     for(int b=1;b<=n;b++) res+=e[mb[b]][b];
45     return res;
46 }
47 
48 //Main
49 bool cmp(node x,node y)
50 {
51     return x.l<y.l;
52 }
53 int main()
54 {
55     scanf("%d",&n);
56     for(int a=1;a<=n;a++)
57         for(int b=1;b<=n;b++)
58             e[a][b]=-inf;
59     for(int i=1;i<=n;i++){
60         for(int j=1;j<=n;j++){
61             int tmp;
62             scanf("%d",&tmp);
63             e[i][j]=tmp;
64         }
65     }
66     ll ans=KM();
67     printf("%lld\n",ans);
68 
69     //存储的是第i个女生的男朋友编号
70     for(int i=1;i<=n;i++) sto[i]=mb[i];
71 
72     int cot=0;
73     for(int i=1;i<=n;i++){
74         int v=i;
75         int u=sto[i];
76         int tmp=e[u][v];
77         e[u][v]=0;
78         if(KM()<ans){
79             cot++;
80             last[cot].l=u;
81             last[cot].r=v;
82         }
83         e[u][v]=tmp;
84     }
85     sort(last+1,last+1+cot,cmp);
86     for(int i=1;i<=cot;i++)
87         printf("%d %d\n",last[i].l,last[i].r);
88     return 0;
89 }
View Code

 

posted @ 2020-07-16 22:23  古比  阅读(232)  评论(0编辑  收藏  举报