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 }