BZOJ2597 WC2007 剪刀石頭布

2022-05-30 19:36:11 字數 2602 閱讀 8691

在一些一對一遊戲的比賽(如下棋、桌球和羽毛球的單打)中,我們經常會遇到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列的數字矩陣:一共n行,每行n列,數字間用空格隔開。

在第(i+1)行的第j列的數字如果是1,則表示i在已經發生的比賽中贏了j;該數字若是0,則表示在已經發生的比賽中i敗於j;該數字是2,表示i和j之間的比賽尚未發生。數字矩陣對角線上的數字,即第(i+1)行第i列的數字都是0,它們僅僅是佔位符號,沒有任何意義。

輸入檔案保證合法,不會發生矛盾,當ij時,第(i+1)行第j列和第(j+1)行第i列的兩個數字要麼都是2,要麼乙個是0乙個是1。

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

輸出檔案的第2行開始有乙個和輸入檔案中格式相同的n行n列的數字矩陣。第(i+1)行第j個數字描述了i和j之間的比賽結果,1表示i贏了j,0表示i負於j,與輸入矩陣不同的是,在這個矩陣中沒有表示比賽尚未進行的數字2;對角線上的數字都是0。輸出矩陣要保證合法,不能發生矛盾。

3

0 1 2

0 0 2

2 2 0

1

0 1 0

0 0 1

1 0 0

神題...

考慮補集轉化,滿足條件的不好求,那就求不滿足條件的。

設第\(i\)個人贏了\(val_i\)次,那麼不滿足條件的三元組個數就是:

\[\sum_^\binom=\sum_^val_i(val_i-1)/2

\]考慮網路流建圖:

那麼這個圖的每種最大流都表示一種可行的方案。

現在我們的目的就是給這個圖加上費用,使得費用最小。

那麼對於點\(a_i\),若流向\(t\)的流量為\(x\),費用就是\(x(x-1)/2\),但是這裡是乙個二次的增長,一般的建圖就做不了了。

可以考慮把這條邊拆成\(n\)條,每條容量為\(1\),費用依次遞增,即費用為\(0,1,2,...,n-1\),那麼可以發現,由於費用流每次增廣都會選擇最小的那條邊,所以流量為\(x\)時費用為\(x(x-1)/2\),即滿足條件。

然後建完圖跑最小費用最大流,然後拿總方案減一下就好了。

輸出方案隨便列舉一下那條邊流滿了就好了。

#includeusing namespace std;

void read(int &x)

void print(int x)

void write(int x)

const int maxn = 2e5+10;

const int inf = 1e9;

int n,s,t,tot=1,cnt,cost;

int head[maxn],vis[maxn],dis[maxn],val[maxn],mp[102][102];

struct edgee[maxn];

void add(int u,int v,int w,int c) ,head[u]=tot;}

void ins(int u,int v,int w,int c)

int bfs()

} return dis[t]0&&dis[e[i].to]==dis[x]+e[i].c)

return used;

}int mcmf()

int tmp[5],top,mark;

int main()

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

for(int j=val[i];j<=n;j++) ins(i,t,1,j);

for(int i=1;i<=n;i++) ans-=val[i]*(val[i]-1)/2;

write(ans-mcmf());

for(int x=n+1;x<=cnt;x++)

mp[tmp[mark]][tmp[mark^1]]=1;

mp[tmp[mark^1]][tmp[mark]]=0;

} for(int i=1;i<=n;i++,puts("")) for(int j=1;j<=n;j++) printf("%d ",mp[i][j]);

return 0;

}

bzoj2597 Wc2007 剪刀石頭布

今天注意力明顯不集中哎 頹 1a 了這道網路流題,思路確實神。題目是給你一張有向圖,讓你新增一些邊使得任意兩個點 a,b 直接都有一條有向邊,可以從a指向b,也可以由b指向a。讓你最大化三元環的數目。according to 姜爺,用補集思想,環不好搞,考慮三個點不成環,那那就是有乙個點連向其它的兩...

bzoj2597 Wc2007 剪刀石頭布

直接求不好求引入未知數,考慮採用補集轉化 對於一次非剪刀石頭布的情況,定是乙個人贏了另兩個人 若知道乙個人共贏了多少人,那麼就貢獻了n n 1 2種不同的情況 更一般的,乙個人如果多贏了乙個人,他的新增的貢獻就是他當前沒有加上這個人時已經贏了的人 費用流。st 比賽 人 ed,費用是遞增的,對於人拆...

bzoj2597 Wc2007 剪刀石頭布

time limit 20 sec memory limit 128 mbsec special judge submit 1765 solved 763 submit status discuss 在一些一對一遊戲的比賽 如下棋 桌球和羽毛球的單打 中,我們經常會遇到a勝過b,b勝過c而c又勝過a...