1. 程式人生 > >解題:WC2007 石頭剪刀布

解題:WC2007 石頭剪刀布

題面

要我們把邊定向,最大化留下來的三元環數目......並不能直接做,考慮容斥,去掉不合法的數目。

那麼三個點不成環當且僅當有一個點出度為2一個點入度為2,發現最終答案就是$C_n^3-\sum C_{outdeg}^2$

 1 #include<queue>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 const int N=10005,M=100005,inf=1e9;
 7 int p[N],noww[2
*M],goal[2*M],flow[2*M],cost[2*M]; 8 int mflw[N],mcst[N],pren[N],pree[N],queu[N],degr[N]; 9 int game[N][N],gamx[N],gamy[N],numb[N]; queue<int> qs; 10 int n,m,s,t,t1,t2,t3,t4,id,rd,cnt,num,ans; 11 void link(int f,int t,int v,int c) 12 { 13 noww[++cnt]=p[f],p[f]=cnt; 14 goal[cnt]=t,flow[cnt]=v,cost[cnt]=c;
15 noww[++cnt]=p[t],p[t]=cnt; 16 goal[cnt]=f,flow[cnt]=0,cost[cnt]=-c; 17 } 18 void Init(int st,int ed) 19 { 20 memset(mflw,0x3f,sizeof mflw); 21 memset(mcst,0x3f,sizeof mcst); 22 memset(queu,0,sizeof queu),pren[ed]=-1; 23 qs.push(st),queu[st]=true,mcst[st]=0; 24 } 25 bool SP(int st,int
ed) 26 { 27 Init(st,ed); 28 while(!qs.empty()) 29 { 30 int tn=qs.front(); 31 qs.pop(),queu[tn]=false; 32 for(int i=p[tn],g;i;i=noww[i]) 33 if(mcst[g=goal[i]]>mcst[tn]+cost[i]&&flow[i]) 34 { 35 pree[g]=i,pren[g]=tn; 36 mcst[g]=mcst[tn]+cost[i]; 37 mflw[g]=min(mflw[tn],flow[i]); 38 if(!queu[g]) qs.push(g),queu[g]=true; 39 } 40 } 41 return ~pren[ed]; 42 } 43 void MCMF(int st,int ed) 44 { 45 while(SP(st,ed)) 46 { 47 ans+=mflw[ed]*mcst[ed],id=ed; 48 while(id!=st) 49 { 50 flow[pree[id]]-=mflw[ed]; 51 flow[pree[id]^1]+=mflw[ed]; 52 id=pren[id]; 53 } 54 } 55 } 56 int main() 57 { 58 scanf("%d",&n),cnt=1,s=n+1,num=t=n+2; 59 for(int i=1;i<=n;i++) 60 for(int j=1;j<=n;j++) 61 { 62 scanf("%d",&game[i][j]); 63 if(game[i][j]==2) 64 { 65 if(i<=j) 66 { 67 num++,gamx[num]=i,gamy[num]=j; 68 link(num,i,1,0),link(num,j,1,0); 69 numb[i]++,numb[j]++,link(s,num,1,0); 70 } 71 } 72 else degr[i]+=game[i][j]; 73 } 74 for(int i=1;i<=n;i++) 75 { 76 ans+=degr[i]*degr[i]; 77 for(int j=1;j<=numb[i];j++) 78 link(i,t,1,2*(degr[i]+j)-1); 79 } 80 MCMF(s,t); 81 printf("%d\n",n*(n-1)*(n-2)/6-(ans-n*(n-1)/2)/2); 82 for(int i=t+1;i<=num;i++) 83 { 84 int oppo,numx=gamx[i],numy=gamy[i]; 85 for(int j=p[i];j;j=noww[j]) 86 if(goal[j]!=s&&!flow[j]) 87 {oppo=goal[j]; break;} 88 game[numx][numy]=oppo==numx; 89 game[numy][numx]=game[numx][numy]^1; 90 } 91 for(int i=1;i<=n;i++,puts("")) 92 for(int j=1;j<=n;j++) 93 printf("%d ",game[i][j]); 94 return 0; 95 }
View Code