WC2007 剪刀石頭布(最大流)

2022-05-19 20:26:25 字數 1798 閱讀 8361

洛古

一句話題意:給定一張圖,每兩點之間有一條有向邊或無向邊,把所有無向邊定向,使圖中三元環個數盡量多

因為原圖是乙個完全圖,假設圖中任意三點都能構成三元環,那麼途中三元環的個數為:\(\binom\)。

那麼如果乙個三元組不是三元環,那麼有乙個點的出度為2。

我們假設乙個點的出度為d,那麼對於這個點,三元環會減少\(\frac\)

所以三元環的數量為:\(\binom- \sum_^n\binom=\binom- \sum_^n\frac\)

所以我們要最小化:$ \sum_^n\frac$的值。

怎麼做呢?

如果我們對於一條無向邊,可能讓u出度+1,也可能讓v出度+1,非黑即白,所以我們可以考慮費用流。

觀察柿子\(\frac\),容(hen)易(nan)想到小學等差數列求和公式,於是我們可以將乙個點的貢獻看成\((0+1+2+3+……+d[i]-1)\)

把每一條邊看成乙個點,從源點向每條邊連一條容量為1,費用為0的邊。

對於一條無向邊,往u,v分別建一條容量為1,費用為0的邊。

有向邊則把邊和v建一條容量為1,費用為0的邊。

每個點向匯點連n條容量為1,費用為0-(n-1)遞增的邊,表示上面的等差數列(可以表示出任何出度的情況)

最後就是費用流的板子了

**如下:

#includeusing namespace std;

#define il inline

#define re register

#define inf 123456789

#define debug printf("now is line : %d\n",__line__)

il int read()

while(c>='0'&&c<='9') x=x*10+c-48,c=getchar();

return x*f;

}#define maxn 105

#define maxm 105*105

struct edge

e[maxm<<3];

int n,a[maxn][maxn],s,t,maxflow,cost,vis[maxm],dis[maxm],head[maxm],cnt=1,pa;

il void add(int u,int v,int val,int w)

; head[u]=cnt;

e[++cnt]=(edge);

head[v]=cnt;

}queueq;

il bool spfa()}}

}return dis[t]!=2139062143;

}il int dfs(int u,int mi)

vis[u]=1;

int use=0;

for(re int i=head[u];i;i=e[i].next)}}

return use;

}il void dinic()

}int ans=((n-1)*(n-2)*n)/6;

ans-=cost;

printf("%d\n",ans);

}int main()

else if(a[i][j]==1) add(s,n*n+j,1,0);

else add(s,n*n+i,1,0);}}

for(re int i=1;i<=n;++i)

dinic();

for(re int i=1;i<=n;++i)}}

}for(re int i=1;i<=n;++i,puts(""))

return 0;

}

Wc2007 剪刀石頭布

題目描述 bzluogu 題解 最小費用流。對於三支隊伍,勝負情況只有 2 種。一種是形成三元環,另一種是 x 贏兩場,y 贏一場,z 沒贏過。所以我們統計一下另一種最少有多少種就好了。最後答案就是 c 3 n k 對於乙個隊伍 x 若其勝場數為 w x 則會造成的負貢獻為 c 2 不會搞?作差啊。...

WC2007 剪刀石頭布

正著求不太好求,但是不是剪刀石頭布的又很好表示 三個人中恰好有乙個人贏了兩場。所以我們考慮讓這種三元組數量最少使得剪刀石頭布最多。考慮乙個人如果贏了i場,那麼他對 非剪刀石頭布的三元組的貢獻是 i i 1 2 也就是他和任意兩個被他擊敗的人都可以組成三元組。並且每個人的貢獻都是獨立的,不會有重複 因...

WC2007 剪刀石頭布 Solution

給一張競賽圖,圖中還有一些邊沒有定向,現在要把它們重新定向,要求重定向之後三元環盡量多。直接考慮不可取,逆向思維。算出極限情況可能出現三元環的個數,那麼就是n n 1 n 2 6 dfrac 6n n 1 n 2 接下來考慮什麼情況會拆毀三元環。考慮乙個點的負場情況來判斷少了多少三元環。如果乙個點負...