bzoj2756 SCOI2012 奇怪的遊戲

2022-05-02 04:24:10 字數 2540 閱讀 8637

blinker最近喜歡上乙個奇怪的遊戲。 

這個遊戲在乙個 n*m 的棋盤上玩,每個格仔有乙個數。每次 blinker 會選擇兩個相鄰的格仔,並使這兩個數都加上 1。 

現在 blinker 想知道最少多少次能使棋盤上的數都變成同乙個數,如果永遠不能變成同乙個數則輸出-1。 

輸入的第一行是乙個整數t,表示輸入資料有t輪遊戲組成。 

每輪遊戲的第一行有兩個整數n和m, 分別代表棋盤的行數和列數。 

接下來有n行,每行 m個數。 

對於每個遊戲輸出最少能使遊戲結束的次數,如果永遠不能變成同乙個數則輸出-1。

2 2 2

1 2

2 3

3 3

1 2 3

2 3 4

4 3 2

2 -1

【資料範圍】 

對於30%的資料,保證  t<=10,1<=n,m<=8 

對於100%的資料,保證  t<=10,1<=n,m<=40,所有數為正整數且小於1000000000 

正解:二分+最大流。

這道題還是很不容易想啊,不過我寫了個騙分居然有$90$分。。

首先我們肯定是要黑白染色,相鄰的點染不同的顏色。

然後我們按照格仔數分奇偶討論:

如果格仔數為偶數,那麼黑點和白點個數相同,於是所有黑點的和與所有白點的和必須相同,否則一定不合法。

因為當黑點和白點個數相同時,每個點的權值$+1$,等價於將相鄰的上下兩點匹配一次,所以我們發現每個點的最終權值是滿足單調性的。也就是說如果$v$合法,那麼$v+1$也一定合法,於是我們直接二分最終的權值,建圖跑最大流就行了。

當格仔數為奇數時,黑點與白點個數不同。那麼我們可以直接算出最終每個格仔的權值。

由$v*num_-sum_=v*num_-sum_$,解得$v=(sum_-sum_)/(num_-num_)$。

$num$為格仔數量,$sum$為初始的格仔權值和。

那麼我們判斷一下$v$是否合法就行了。

1 #include 2

#define il inline

3#define rg register

4#define ll long long

5#define inf (1ll<<60)

6#define n (1000010)

7#define pos(i,j) ((i-1)*m+j)89

using

namespace

std;

1011

struct edgeg[n<<1

];12

13int head[n],d[n],q[n],a[42][42

],s,t,n,m,num,tot;

14ll x,y,ans;

1516 il int

gi()

2324 il void insert(rg int

from,rg int

to,rg ll cap),head[from]=num; return;26

}2728 il int bfs(rg int s,rg int

t)39}40

}41return

d[t];42}

4344 il ll dfs(rg int x,rg int

t,rg ll a)

51 g[i].flow+=f,g[i^1].flow-=f;

52 flow+=f,a-=f; if (!a) return

flow;53}

54}55return

flow;56}

5758 il ll maxflow(rg int s,rg int

t)63

64 il int

check(rg ll key)

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

72for (rg int j=1;j<=m;++j)

73if ((i+j)&1)79

maxflow(s,t);

80for (rg int i=1,k=2;i<=n;++i)

81for (rg int j=1;j<=m;++j,k+=2)82

if (g[k].flow!=g[k].cap) return0;

83return1;

84}8586 il void

work()

93if (n*m%2==0

)95 rg ll l=tot,r=1ll<<50

,mid;

96while (l<=r)

100 printf("

%lld\n

",(ans*n*m>>1)-x);

101 } else

103if (check(x)) printf("

%lld\n

",x*((n*m)>>1)-x);

104else puts("-1"

);105

}106

return

;107

}108

109int

main()

bzoj2756 SCOI2012 奇怪的遊戲

description blinker最近喜歡上乙個奇怪的遊戲。這個遊戲在乙個 n m 的棋盤上玩,每個格仔有乙個數。每次 blinker 會選擇兩個相鄰 的格仔,並使這兩個數都加上 1。現在 blinker 想知道最少多少次能使棋盤上的數都變成同乙個數,如果永遠不能變成同 乙個數則輸出 1。inp...

bzoj2756 SCOI2012 奇怪的遊戲

description blinker最近喜歡上乙個奇怪的遊戲。這個遊戲在乙個 n m 的棋盤上玩,每個格仔有乙個數。每次 blinker 會選擇兩個相鄰的格仔,並使這兩個數都加上 1。現在 blinker 想知道最少多少次能使棋盤上的數都變成同乙個數,如果永遠不能變成同乙個數則輸出 1。input...

bzoj2756 SCOI2012 奇怪的遊戲

傳送門 思路 先黑白染色,設白格個數為cnt0,和為sum0,黑格個數為cnt1,和為sum1,假設最後所有點都變成了x 那麼如果cnt0 cnt1就是格仔數為奇數時 cnt0 x sum0 cnt1 x sum1 x sum0 sum1 cnt0 cnt1 格仔為偶數時x沒有意義 我們就要想新的方...