ZJOI 2011 最小割 分治

2021-07-26 16:35:50 字數 1609 閱讀 9882

小白在圖論課上學到了乙個新的概念——最小割,下課後小白在筆記本上寫下了如下這段話: 「對於乙個圖,某個對圖中結點的劃分將圖中所有結點分成兩個部分,如果結點s,t不在同乙個部分中,則稱這個劃分是關於s,t的割。 對於帶權圖來說,將所有頂點處在不同部分的邊的權值相加所得到的值定義為這個割的容量,而s,t的最小割指的是在關於s,t的割中容量最小的割」 現給定一張無向圖,小白有若干個形如「圖中有多少對點它們的最小割的容量不超過x呢」的疑問,小藍雖然很想回答這些問題,但小藍最近忙著挖木塊,於是作為仍然是小藍的好友,你又有任務了。

輸入檔案第一行有且只有乙個正整數t,表示測試資料的組數。 對於每組測試資料, 第一行包含兩個整數n,m,表示圖的點數和邊數。 下面m行,每行3個正整數u,v,c(1<=u,v<=n,0<=c<=10^6),表示有一條權為c的無向邊(u,v) 接下來一行,包含乙個整數q,表示詢問的個數 下面q行,每行乙個整數x,其含義同題目描述。

對於每組測試資料,輸出應包括q行,第i行表示第i個問題的答案。對於點對(p,q)和(q,p),只統計一次(見樣例)。

兩組測試資料之間用空行隔開。

思路:

直接暴力顯然超時,容易想到分治解決(然而並不會搞)。

首先需要知道最小割的乙個性質,若不考慮多個最小割的情況,設s1-t1的最小割割集為c1,s2-t2的最小割割集為c2,則c1,c2必然不會相互跨立,這個結論可通過反證法得到。由這個性質我們可以發現整個圖的最小割構成了一棵最小割樹,即其最小割數量不超過n - 1個。

有了這個性質就很好分治了,我們每次從點集中任選s,t做最小割,將點集中的點按最後是與s或是t聯通分為兩個點集遞迴處理,並更新兩邊的點之間的最小割。

**:

#include #include #include #include #include #define for(i,j,k) for(int i = j;i <= (int)k;i++)

#define forr(i,j,k) for(int i = j;i >= (int)k;i--)

#define set(i,j) memset(i, j, sizeof i)

using namespace std;

const int n = 160, m = 6100;

struct dinic

void clearflow()

void add(int x, int y, int w)

bool bfs()

}return d[t];

}int dfs(int h, int maxf)

if(!maxf) return sumf;

}return sumf;

}int mincut(int s, int t)

return ret;

}}f;

int t, n, m, q;

int cut[n][n], id[n], tmp[n];

void solve(int l, int r)

int main()

set(cut, 0x7f);

solve(1, n);

scanf("%d", &q);

while(q--)

if(t) puts("");

}return 0;

}

ZJOI 2011 最小割 分治

題目鏈結 bzoj點我 洛谷點我 題目描述 小白在圖論課上學到了乙個新的概念 最小割,下課後小白在筆記本上寫下了如下這段話 對於乙個圖,某個對圖中結點的劃分將圖中所有結點分成兩個部分,如果結點s,t不在同乙個部分中,則稱這個劃分是關於s,t的割。對於帶權圖來說,將所有頂點處在不同部分的邊的權值相加所...

ZJOI2011 營救皮卡丘

題面 神仙題。做最小路徑覆蓋。有乙個很像的地方,就是最小路徑覆蓋必須覆蓋到每個點,這道題也一樣。這道題有4個和最小路徑覆蓋不一樣的地方 可以重複訪問 這個可以用 floyed 傳遞閉包解決 每條路徑必須從原點出發 每個點必須被 到達 並不能乙個節點成乙個路徑 假設已經訪問了 1.x 那麼至少有乙個人...

ZJOI2011 營救皮卡丘

似乎這玩意兒叫做 k 路徑覆蓋問題 可以發現 k 個人每個人走過的點集不相交 就是有 n 個點 m 條邊的圖,邊有邊權,從 0 出發,中途如果經過點 u 那麼之前必須經過點 u 1 可以從點 s 出發最多 k 次,問走到 n 的最小花費 那麼題目就轉化成了用不超過 k 條不相交的鏈覆蓋整張圖的最小代...