bzoj2756 SCOI2012 奇怪的遊戲

2022-08-22 21:27:08 字數 1346 閱讀 9499

傳送門:

思路:先黑白染色,設白格個數為cnt0,和為sum0,黑格個數為cnt1,和為sum1,假設最後所有點都變成了x

那麼如果cnt0!=cnt1就是格仔數為奇數時

cnt0*x-sum0=cnt1*x-sum1

x=(sum0-sum1)/(cnt0-cnt1)

格仔為偶數時x沒有意義

我們就要想新的方法

格仔為偶數,那麼如果x合法,那麼x+1也會合法

這個可以構造證明,兩兩配對+1即可

所以這種情況可以二分

知道x後就可以用網路流check了

s向白格連x-num[i][j]的邊

白點向相鄰黑點連inf的邊,

黑點向t連x-num[i][j]的邊即可

#include#include#include#includetypedef long long ll;

const int maxn=1610,maxm=20010;

const ll inf=1ll<<50;

const int dx=;

const int dy=;

using namespace std;

int cas,n,m,s=maxn-2,t=maxn-1,cnt0,cnt1;

int pre[maxm],now[maxn],son[maxm],tot,q[maxn+10],head,tail,dis[maxn];

ll sum0,sum1,x,val[maxm],num[45][45],maxs;

void add(int a,int b,ll c)

void ins(int a,int b,ll c)//,printf("%d %d %lld\n",a,b,c);

//0是白,即x+y為偶數的格仔,1是黑

int id(int x,int y)

void init()

}bool bfs()

} return dis[t]>0;

}ll find(int x,ll low)

if (!y) dis[x]=-1;

return res;

}bool dinic(ll lim)

}else ins(id(i,j),t,lim-num[i][j]);

ll res=0;

while (bfs()) res+=find(s,inf);

//printf("%lld %lld\n",res,flow);

return res==flow;

}void work()

else

printf("%lld\n",ans*cnt0-sum0); }}

int 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 奇怪的遊戲

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