poj1815 最小割點集

2021-08-08 12:09:13 字數 1549 閱讀 6882

【題目大意】

現代社會人們都靠**通訊。a 與 b 能通訊當且僅當 a 知道 b 的**號或者 a

知道 c 的**號且 c 與 b 能通訊。若 a 知道 b 的**號,那麼 b 也知道 a 的電

話號。然而不好的事情總是會發生在某些人身上,比如他的**本丟了,同時他

又換了**號,導致他跟所有人失去了聯絡。現在給定 n 個人之間的通訊關係

以及特定的兩個人 s 和 t,問最少幾個人發生不好的事情可以導致 s 與 t 無法通

信並輸出這些人。如果存在多組解,輸出字典序最小的一組。(2 <= n <= 200)

【建模方法】

此題是求乙個最小點割集,但是要求輸出方案且要字典序最小。首先仍是拆點構

圖,求一次最小割記為 ans。之後我們採取貪心的策略,從 1 至 n 列舉刪點,如

果最小割不變,說明該點不可能在最小割中,我們再把該點加入到網路中;否則

最小割一定變小了,用這個較小值更新 ans,記錄該點是乙個解並不再將其放回。

重複這個過程,把所有點都掃瞄一遍後結果就

#include#include#include#includeusing namespace std;

int bmap[205][205];

typedef int cap_type;

#define max_v 800 + 30 + 16

struct edge

};vector g[max_v];

int level[max_v];

int iter[max_v];

void add_edge(int from, int to, int cap)

void bfs(int s)

} }}cap_type dfs(int v, int t, cap_type f)

for (int &i = iter[v]; i < g[v].size(); ++i)

}} return 0;

}cap_type max_flow(int s, int t)

memset(iter, 0, sizeof(iter));

cap_type f;

while ((f = dfs(s, t, 0x3f3f3f3f)) > 0)

}}int ans[205];

int vis[205];

int tot = 0;

int main()

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

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

for(int j=i+1;j<=n;j++)

int res = max_flow(s,t+n);

memset(vis,0,sizeof(vis));

printf("%d\n",res);

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

for(int j=1;j<=n;j++)

}int tmp = max_flow(s,t+n);

//printf("%d %d %d\n",i,tmp,res);

if(tmp0){

for(int i=0;i

poj 1815(最小割 割集)

思路 題目要求是剔除多少個點,可以將其轉化為剔除多少條邊,因此需要拆點,將點i拆成i,i n,便容量為1,表示每個人起的傳遞作用只能是一次。然後就是列舉了,刪除某條邊,如果求出的最小割比原來的要小,說明減少的是割邊集。1 include2 include3 include4 include5 inc...

poj 1815 最小點割集

最小點割集求解方法 1.有向圖 把乙個點拆成 i,i n 2個點,之間容量為1。如果i,j 2個點在原圖中聯通,則將i n,j相連,容量為無窮大。然後求最小割,可見被最小割割到的都是容量是1的邊,如果割到一條inf,說明沒有最小點割集。而且那些邊必將連著i,i n,於是i就是被割的點。2.無向圖 把...

poj 1815 最小割 列舉

題意 給乙個無向圖,求最少刪除多少個點,使得從s到t不連通,並輸出字典序最小的方案數。思路 拆點,從s到t跑一遍最小割,求出最少刪除的點數。關鍵是如何求字典序最小的方案,可以從1到n列舉每個點 拆成的邊 是否可以在最小割中,即把這個點所連的所有邊斷掉,再跑一遍最小割。如果最小割減小,就把這個點從割集...