【UOJ168】元旦老人与丛林【图论证明】【最大权闭合子图】【dinic动态推流】
題意:給一張無向圖,判斷能否分成兩個生成森林。
n≤2×103,m≤4×103n\leq 2\times 10^3,m\leq 4\times 10^3n≤2×103,m≤4×103
題目中這樣的圖稱為“叢林”,下面以此來簡稱。
結論 一張圖是叢林的充要條件是它的每一個子圖 G=(∣V∣,∣E∣)G=(|V|,|E|)G=(∣V∣,∣E∣) 有 ∣E∣≤2∣V∣?2|E|\leq 2|V|-2∣E∣≤2∣V∣?2
必要性顯然。
充分性:考慮歸納法,當 ∣V∣=1|V|=1∣V∣=1 時顯然成立,∣V∣>1|V|>1∣V∣>1 假設結點數小于 ∣V∣|V|∣V∣ 的滿足條件的圖都是叢林。
引理1 定義滿圖為滿足 ∣E∣=2∣V∣?2|E|=2|V|-2∣E∣=2∣V∣?2 的圖,對于當前圖的兩個交非空的子圖 G1=(V1,E1),G2=(V2,E2)G_1=(V_1,E_1),G_2=(V_2,E_2)G1?=(V1?,E1?),G2?=(V2?,E2?),它們的并也是滿圖。
證明 設它們的交為 G3=(V3,E3)G_3=(V_3,E_3)G3?=(V3?,E3?),并為 G=(V,E)G=(V,E)G=(V,E)。由假設知 ∣E1∣=2∣V1∣?2,∣E2∣=2∣V2∣?2,∣E3∣≤2∣V3∣?2|E_1|=2|V_1|-2,|E_2|=2|V_2|-2,|E_3|\leq 2|V_3|-2∣E1?∣=2∣V1?∣?2,∣E2?∣=2∣V2?∣?2,∣E3?∣≤2∣V3?∣?2,所以 ∣E∣≥2∣V∣?2|E|\geq 2|V|-2∣E∣≥2∣V∣?2。又因為 ∣E∣≤2∣V∣?2|E|\leq 2|V|-2∣E∣≤2∣V∣?2,所以 ∣E∣=2∣V∣?2|E|=2|V|-2∣E∣=2∣V∣?2。得證。
引理2 一個叢林最小的點度數小于 444。
證明 顯然。
對于一張滿足右邊的條件的圖,它的每一個真子圖都是叢林。我們考慮它的一個最小的點的度數,如果是 0,1,20,1,20,1,2,就把這些邊連到外面對應個數的生成森林上,得到整張圖是叢林。下面討論度數為 333 的情況。
引理3 當度數為 333 時,設相鄰的三個點為 a,b,ca,b,ca,b,c,刪掉這個點 uuu 及這三條邊后的圖為 GGG,那么一定存在 {x,y}?{a,b,c}\{x,y\}\subseteq \{a,b,c\}{x,y}?{a,b,c} 使得 GGG 中不存在一個滿子圖包含 x,yx,yx,y。
證明 假設 a,b,ca,b,ca,b,c 兩兩都被一個滿子圖包含,把這三個滿子圖合并起來,由引理 1,合并后的圖 FFF 也是滿子圖,即 ∣E(F)∣=2∣V(F)∣?2|E(F)|=2|V(F)|-2∣E(F)∣=2∣V(F)∣?2。我們加入 uuu 和這三條邊,就得到了一張 ∣E∣=2∣V∣?1|E|=2|V|-1∣E∣=2∣V∣?1 的圖,它是原圖的子圖,矛盾,得證。
我們在 G1G_1G1? 中加入一條邊 (x,y)(x,y)(x,y),因為不存在包含 (x,y)(x,y)(x,y) 的滿圖,所以加入后 G1G_1G1? 仍然是叢林。考慮這棵叢林的兩棵生成樹,在包含 (x,y)(x,y)(x,y) 的樹上斷掉這條邊,然后 uuu 分別通過 x,yx,yx,y 連接兩個連通分量,剩下一個直接連,就構造了兩棵原圖的生產樹,原命題得證。
現在我們要判斷是否對于每一個子圖都有
∣E∣≤2∣V∣?2|E|\leq 2|V|-2∣E∣≤2∣V∣?2
∣E∣?2∣V∣≤?2|E|-2|V|\leq -2∣E∣?2∣V∣≤?2
就是最大權閉合子圖對于每條邊建一個點,從 SSS 連邊權為 111 的邊,向兩個端點連 +∞+\infin+∞ 的邊,每個點到 TTT 連邊權為 222 的邊,跑最小割即可。
設最小割為 ccc,邊數為 mmm,我們需要判斷是否
m?c≤?2m-c\leq -2m?c≤?2
然后你會發現至少有一個大小為 mmm 的割,所以會永遠輸出 No。
冷靜分析,這樣的原因是空圖的存在。所以我們要枚舉一個點強制選,也就是斷掉對應的邊,最后最小割 +2+2+2,當 c?2<mc-2<mc?2<m 時輸出 No。
然后要跑 nnn 次完整的 dinic,會 T。注意到每次流量改變是常數,所以在斷掉 (u,v)(u,v)(u,v) 時從 uuu 到 SSS 流 c(u,v)c(u,v)c(u,v) 的流量來模擬退流,然后物理斷掉這條邊。再從 SSS 到 TTT 跑 dinic,因為是在幾乎已經增廣完的殘余網絡上跑的所以很快。
#include <iostream> #include <cstdio> #include <cstring> #include <cctype> #include <queue> #define MAXN 6005 #define MAXM 40005 using namespace std; const int INF=0x7fffffff; inline int read() {int ans=0;char c=getchar();while (!isdigit(c)) c=getchar();while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();return ans; } struct edge{int u,v,c;}e[MAXM]; int head[MAXN],cur[MAXN],nxt[MAXM],cnt=1; inline void insert(int u,int v,int c){e[++cnt]=(edge){u,v,c};nxt[cnt]=head[u];head[u]=cnt;} inline void addnode(int u,int v,int c){insert(u,v,c),insert(v,u,0);} int dis[MAXN]; bool bfs(int S,int T) {queue<int> q;q.push(T);memset(dis,-1,sizeof(dis));dis[T]=0;while (!q.empty()){int u=q.front();q.pop();for (int i=head[u];i;i=nxt[i])if (e[i^1].c&&dis[e[i].v]==-1){dis[e[i].v]=dis[u]+1;q.push(e[i].v);if (e[i].v==S) return true;}}return false; } int dfs(int u,int f,int T) {if (u==T||!f) return f;int used=0;for (int& i=cur[u];i;i=nxt[i])if (e[i].c&&dis[u]==dis[e[i].v]+1){int w=dfs(e[i].v,min(e[i].c,f),T);e[i].c-=w,e[i^1].c+=w;f-=w,used+=w;if (!f) break;}if (!used) dis[u]=-1;return used; } inline int dinic(int S,int T,int f=INF) {int ans=0;while (f>ans&&bfs(S,T))memcpy(cur,head,sizeof(head)),ans+=dfs(S,f-ans,T);return ans; } int pos[MAXN]; int solve() {memset(head,0,sizeof(head));memset(nxt,0,sizeof(nxt));cnt=1;int n,m;n=read(),m=read();int S=n+m+1,T=S+1;for (int i=1;i<=m;i++){addnode(n+i,read(),INF);addnode(n+i,read(),INF);addnode(S,n+i,1);}for (int i=1;i<=n;i++) addnode(i,T,2),pos[i]=cnt;int ans=dinic(S,T);for (int i=1;i<=n;i++){int f=e[pos[i]].c;e[pos[i]].c=e[pos[i]^1].c=0;if (f) ans-=dinic(i,S,f);if (i>1) e[pos[i-1]^1].c=2;ans+=dinic(S,T);if (ans<m) return puts("No"),0;}puts("Yes");return 0; } int main() {for (int T=read();T;T--) solve();return 0; }總結
以上是生活随笔為你收集整理的【UOJ168】元旦老人与丛林【图论证明】【最大权闭合子图】【dinic动态推流】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 儿童怎样减肥
- 下一篇: 【九省联考2018】秘密袭击【树形dp】