1. 程式人生 > 實用技巧 >P3967 [TJOI2014]匹配 KM演算法

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