解题: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

猜你喜欢

转载自www.cnblogs.com/ydnhaha/p/10181586.html
今日推荐