【題目大意】
現代社會人們都靠**通訊。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列舉每個點 拆成的邊 是否可以在最小割中,即把這個點所連的所有邊斷掉,再跑一遍最小割。如果最小割減小,就把這個點從割集...