SCOI2012 二分法 最大流 奇怪的遊戲

2021-06-13 08:42:38 字數 2227 閱讀 1444

這道題初看也許會感覺無法下手,由於每次操作都是相鄰的兩個,所以可以考慮將棋盤黑白染色,這樣我們可以對黑色的格仔和白色的格仔單獨考慮。

設黑色格仔個數為cnt1,總和為sum1,白色格仔個數為cnt2,總和為sum2,最終所有格仔都變成了x,則很容易寫出下列的關係式:

cnt1 *x - sum1 = cnt2 * x - sum2

=> x * (cnt1 - cnt2) = sum1 - sum2

=> x = (sum1 - sum2)/ (cnt1 - cnt2)

現在討論cnt1 與 cnt2的情況:

1、若cnt1 = cnt2,則說明在sum1 = sum2的情況下,

若x可行,則x+1同樣可以,這樣我們可以通過二分的方法找出最小的滿足條件的x,求出最小步數;若sum1 != sum2則無解。

2、若cnt1!= cnt2,則我們解出了乙個x

這個x必須要滿足三個條件:

(1)x必須為整數

(2)x不小於所有格仔的最大值

(3)x必須要通過檢驗

如果x滿足這三個條件,則我們可以解出最小步數,否則無解。

那麼我們怎樣檢驗x是否可行呢,這個需要通過網路流來驗證。

設map[i][j]為格仔對應的數字,

對於每個黑色的格仔,從源點連一條邊,容量為x - map[i][j],並且對它周圍的四個白色格仔連一條邊容量為inf;對於每個白色格仔,向匯點連一條邊,容量為x - map[i][j]

設最大流為maxflow,若maxflow= (n * m * x - sum1 -sum2) >> 1的話,說明存在方案可以使所有數變成x,同時最小步數minstep = (n * m * x - sum1 - sum2) >> 1

注意到格仔的數可能很大,所以要使用longlong型別

這樣就解決了本題。

**:

#include#includeusing namespace std;

const int maxn = 50;

const int maxpoint = 3000;

const int maxm = 100000;

const long long inf = 0x3f3f3f3f3f3f3f3fll;

struct edge

e[maxm];

int map[maxn][maxn],head[maxpoint];

int dis[maxpoint],gap[maxpoint],cur[maxpoint],pre[maxpoint];

int t,n,m;

int ne,s,t,nodenum;

long long maxw,cnt1,sum1,cnt2,sum2,com;

void init()

inline int max(long long a,long long b)

inline void checkmin(long long &a,long long b)

inline long long gettime(long long x)

void insert(int u,int v,long long c)

long long sap()

aug = -1;

}goto loop;}}

int mind = nodenum;

for(int i = head[u];i != -1;i = e[i].next)

}if(--(gap[dis[u]]) == 0)break;

gap[dis[u] = mind + 1]++;

u = pre[u];

} return maxflow;

}bool check(long long x)

else insert((i - 1) * m + j,t,x - map[i][j]);

} }return ((sap() << 1) == (x * n * m - sum1 - sum2));

}void solve()

if(check(x))printf("%lld\n",gettime(x));

else printf("-1\n");

} }else

if(check(r))printf("%lld\n",gettime(r));

else printf("-1\n"); }}

void readdata()

} solve(); }}

int main()

poj 2112 最大流 二分法

安排c頭牛到某個擠奶器,使得每頭牛需要走的路程中最大路程的距離最小。先用floyd演算法,求出奶牛到每個擠奶器的最短距離,然後從最大的距離二分,當此距離可以使c頭牛,匹配成功,就讓右區間r mid 若不成功,就讓左區間l mid 之後繼續二分。每次二分後,都要重新建圖,另外加超級源點s和超級匯點t,...

二分法最大匹配

關鍵在於如何尋找增廣路徑 初始時最大匹配為空 for 二分圖左半邊的每個點i do 從點i出發尋找增廣路徑。如果找到,則把它取反 即增加了總了匹配數 如果二分圖的左半邊一共有n個點,那麼最多找n條增廣路徑。如果圖中共有m條邊,那麼每找一條增廣路徑 dfs或bfs 時最多把所有邊遍歷一遍,所花時間也就...

C 二分法查詢,遞迴二分法

用二分法來求需要查詢的值.includeusing namespace std 查詢key元素是否存在 int findkey const int buf 100 const int ilen,const int key else right left mid 1 查詢失敗 return 1 查詢k...