Wc2007 剪刀石頭布(費用流)

2021-08-21 06:39:45 字數 4429 閱讀 3223

time limit: 20 sec

memory limit: 128 mb

sec special judge

在一些一對一遊戲的比賽(如下棋、桌球和羽毛球的單打)中,我們經常會遇到a勝過b,b勝過c而c又勝過a的有趣情況,不妨形象的稱之為剪刀石頭布情況。有的時候,無聊的人們會津津樂道於統計有多少這樣的剪刀石頭布情況發生,即有多少對無序三元組(a, b, c),滿足其中的乙個人在比賽中贏了另乙個人,另乙個人贏了第三個人而第三個人又勝過了第乙個人。注意這裡無序的意思是說三元組中元素的順序並不重要,將(a, b, c)、(a, c, b)、(b, a, c)、(b, c, a)、(c, a, b)和(c, b, a)視為相同的情況。

有n個人參加一場這樣的遊戲的比賽,賽程規定任意兩個人之間都要進行一場比賽:這樣總共有場比賽。比賽已經進行了一部分,我們想知道在極端情況下,比賽結束後最多會發生多少剪刀石頭布情況。即給出已經發生的比賽結果,而你可以任意安排剩下的比賽的結果,以得到盡量多的剪刀石頭布情況。

輸入檔案的第1行是乙個整數

n n

,表示參加比賽的人數。

之後是乙個

n' role="presentation" style="position: relative;">nn行

n n

列的數字矩陣:一共

n' role="presentation" style="position: relative;">n

n行,每行

n n

列,數字間用空格隔開。在第(i

+1)' role="presentation" style="position: relative;">(i+

1)(i

+1)行的第

j j

列的數字如果是1,則表示

i' role="presentation" style="position: relative;">i

i在已經發生的比賽中贏了

j j

;該數字若是0,則表示在已經發生的比賽中

i' role="presentation" style="position: relative;">ii敗於

j j

;該數字是2,表示

i' role="presentation" style="position: relative;">ii和

j j

之間的比賽尚未發生。數字矩陣對角線上的數字,即第(i

+1)' role="presentation" style="position: relative;">(i+

1)(i

+1)行第

i i

列的數字都是0,它們僅僅是佔位符號,沒有任何意義。

輸入檔案保證合法,不會發生矛盾,當i≠

j' role="presentation" style="position: relative;">i≠j

i≠j時,第(i

+1) (i+

1)

行第j j

列和第(j

+1)' role="presentation" style="position: relative;">(j+

1)(j

+1)行第i列的兩個數字要麼都是2,要麼乙個是0乙個是1。

輸出檔案的第1行是乙個整數,表示在你安排的比賽結果中,出現了多少剪刀石頭布情況。

輸出檔案的第2行開始有乙個和輸入檔案中格式相同的n行n列的數字矩陣。第(i

+1) (i+

1)

行第j j

個數字描述了

i' role="presentation" style="position: relative;">ii和

j j

之間的比賽結果,1表示

i' role="presentation" style="position: relative;">ii贏了

j j

,0表示

i' role="presentation" style="position: relative;">ii負於

j j

,與輸入矩陣不同的是,在這個矩陣中沒有表示比賽尚未進行的數字2;對角線上的數字都是0。輸出矩陣要保證合法,不能發生矛盾。

sample input

3

0 1 2

0 0 2

2 2 0

sample output
1

0 1 0

0 0 1

1 0 0

100%的資料中,n≤

100' role="presentation" style="position: relative;">n

≤100n≤

100。

' role="presentation" style="position: relative;">

' role="presentation" style="position: relative;">

' role="presentation" style="position: relative;">

' role="presentation" style="position: relative;">

' role="presentation" style="position: relative;">

這道題好強啊。orz!!!!!!!

感覺要完了,看了一大堆還是不會。

這道題需要發現乙個性質,怎麼判斷乙個三元環?因為這是乙個競賽圖,所以對於一組三個點。當他們的入度都為1的時候就會出現乙個環。但是我們是不好判斷這個環的,難道你要讓我列舉所有點?再向下想一想,要是乙個不成環的三個點會怎麼樣?顯然出現乙個入度為2的點,1個出度為2的點,和乙個出度入度為1的點。是不是很妙?

只要有乙個入度為2的點,我們不成環的三元組就多乙個

那我們豈不是可以算不成環的三個點再用總數減一減?

具體來說是這樣的: an

s=cn

3−∑i

=1nc

ingr

ee(i

)2' role="presentation" style="position: relative;">ans

=c3n

−∑ni

=1c2

ingr

ee(i

)ans

=cn3

−∑i=

1nci

ngre

e(i)

2我們要使答案最大那就是後面那一塊最小。我們要做的就是給圖定向,是不是想到了費用流?

沒錯,就是這樣。我們把每條邊看做乙個點,沒有定向的就連兩個點,定了向的就連乙個點。至於每個點的貢獻不是隨度數線性增長的,我們把它拆成很多流量為1的邊就是。

輸出方案的話,看哪條邊被割就知道這條邊的方向了。

code:

#include

#include

#include

#include

#define inf 1000000000

using

namespace

std;

struct lxyeg[1000005];

int n,p,m,s,f,ss,tt,cnt=-1;

int head[20005],data[105][105],dis[40005];

bool vis[20005];

long

long ans;

void add(int op,int ed,int flow,int cost)

bool spfa()}}

if(dis[tt]==0x3f3f3f3f) return

false;

else

return

true;

}int dfs(int u,int a)

return flow;

}int dinic()

return ret;

}int main()

ss=0,tt=n*n+n+1;

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

add(ss,i,1,0),add(i,ss,0,0);

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

for(int j=0;j1,j),add(tt,i,0,-j);

dinic();

printf("%lld\n",n*(n-1)*(n-2)/(1*2*3)-ans);

memset(data,0,sizeof(data));

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

for(int j=1;j<=n;j++)

for(int k=head[i*n+j];k!=-1;k=eg[k].next)

if(eg[k].flow==0)

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

}

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 接下來考慮什麼情況會拆毀三元環。考慮乙個點的負場情況來判斷少了多少三元環。如果乙個點負...