P4249-[WC2007]剪刀石头布【费用流】
正題
題目鏈接:https://www.luogu.com.cn/problem/P4249
題目大意
nnn個(gè)點(diǎn)的競(jìng)賽圖有的邊已經(jīng)確定了方向,要求給剩下的邊確定一個(gè)方向使得圖的三元環(huán)最多。
1≤n≤1001\leq n\leq 1001≤n≤100
解題思路
競(jìng)賽圖如果三個(gè)點(diǎn)不能構(gòu)成三元環(huán)有一個(gè)性質(zhì)就是恰好有一個(gè)點(diǎn)的度數(shù)等于222,可以考慮減去不能構(gòu)成三元環(huán)的方案。
也就說(shuō)對(duì)于一個(gè)點(diǎn)xxx如果我們選出它的兩條出邊那么這個(gè)就不能構(gòu)成三元環(huán)而且只會(huì)在點(diǎn)xxx統(tǒng)計(jì)一次。
所以答案就是
(n3)?∑i=1n(degi2)\binom n 3-\sum_{i=1}^n\binom{deg_i}2(3n?)?i=1∑n?(2degi??)
現(xiàn)在我們要最小化后面那個(gè)東西,這個(gè)就比較簡(jiǎn)單了,因?yàn)閷?duì)于一條沒(méi)有確定的邊要么給xxx加度數(shù)要么給yyy加度數(shù),我們可以考慮費(fèi)用流,如果一條邊可以指向xxx那么就連向點(diǎn)xxx費(fèi)用000流量111。
然后對(duì)于每個(gè)點(diǎn)連接匯點(diǎn)的時(shí)候流量都是一,然后費(fèi)用分別為0,1,2,3,...n?10,1,2,3,...n-10,1,2,3,...n?1就好了。
code
#include<cstdio> #include<cstring> #include<algorithm> #include<queue> using namespace std; const int N=1e5+10; struct node{int to,next,w,c; }a[N*20]; int n,tot=1,s,t,cnt,ans; int p[110][110],c[110][110],ls[N],f[N],mf[N],pre[N]; bool v[N];queue<int> q; void addl(int x,int y,int w,int c){a[++tot].to=y;a[tot].next=ls[x];ls[x]=tot;a[tot].w=w;a[tot].c=c;a[++tot].to=x;a[tot].next=ls[y];ls[y]=tot;a[tot].w=0;a[tot].c=-c;return; } bool SPFA(){memset(f,0x3f,sizeof(f));q.push(s);f[s]=0;v[s]=1;mf[s]=1e9;while(!q.empty()){int x=q.front();q.pop();v[x]=0;for(int i=ls[x];i;i=a[i].next){int y=a[i].to;if(a[i].w&&f[x]+a[i].c<f[y]){f[y]=f[x]+a[i].c;pre[y]=i;mf[y]=min(mf[x],a[i].w);if(!v[y])v[y]=1,q.push(y);}}}return f[t]<=2147483647/3; } void Updata(){int x=t;ans+=mf[t]*f[t];while(x!=s){a[pre[x]].w-=mf[t];a[pre[x]^1].w+=mf[t];x=a[pre[x]^1].to;}return; } int main() {scanf("%d",&n);s=1;t=2;cnt=n+2;for(int i=3;i<=n+2;i++)for(int j=0;j<n;j++)addl(i,t,1,j);for(int i=1;i<=n;i++)for(int j=1;j<=n;j++){int x;p[i][j]=++cnt;scanf("%d",&x);c[i][j]=x;if(i>=j)continue;addl(s,cnt,1,0);if(x==0||x==2)addl(cnt,j+2,1,0);if(x==1||x==2)addl(cnt,i+2,1,0);}while(SPFA())Updata();printf("%d\n",n*(n-1)*(n-2)/6-ans);for(int i=1;i<=n;i++)for(int j=1;j<=n;j++){if(c[i][j]!=2||i>=j)continue;int x=p[i][j];if(a[ls[x]].w)c[i][j]=0,c[j][i]=1;else c[i][j]=1,c[j][i]=0;}for(int i=1;i<=n;i++,putchar('\n'))for(int j=1;j<=n;j++)printf("%d ",c[i][j]);return 0; }總結(jié)
以上是生活随笔為你收集整理的P4249-[WC2007]剪刀石头布【费用流】的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Loj#6247-九个太阳【单位根反演】
- 下一篇: 小米电视如何播放PPT/PDF小米电视如