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沒有意義 我們就要想新的方...