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