日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【LuoguP33294123】[ZJOI2011]最小割[CQOI2016]不同的最小割

發(fā)布時(shí)間:2025/3/16 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【LuoguP33294123】[ZJOI2011]最小割[CQOI2016]不同的最小割 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

鏈接1
鏈接2

題意簡述

第一個(gè)題 : 問圖中有多少不同的最小割數(shù)值
第二個(gè)題 : \(q\) 次詢問圖中多少對(duì)點(diǎn)對(duì)之間的最小割小于 \(x\)

Sol

兩個(gè)都是模板題就放一起了。

求完最小割樹直接暴力 \(O(n^2)\) 弄出所有點(diǎn)對(duì)間最小割 , 然后該干嘛干嘛。


最小割樹的構(gòu)建:

\(Gemory-Hu\; Tree\)算法

對(duì)于一個(gè) \(n\) 個(gè)節(jié)點(diǎn)的圖 , 圖中所有點(diǎn)對(duì)不同的最小割數(shù)目最多只有 \(n-1\) 個(gè) , 可以證明存在一棵樹 , 使得兩點(diǎn)在這棵樹上的最小割即為原圖中的最小割 。
考慮3個(gè)點(diǎn)兩兩之間的最小割 \(C_{u,v},C_{u,t},C_{v,t}\) , 我們已知 \(C_{u,t},C_{v,t}\) , 假設(shè)在\(C_{u,v}\)中 ,不妨假設(shè) \(t\) 被分在了與 \(v\) 在一起的割集 。由于在一個(gè)割中一個(gè)點(diǎn)一定被分在源點(diǎn)或者匯點(diǎn)的一側(cè)割集 , 那么可以推出 \(C_{u,v}\leq C_{u,t}\) , 如果不是那么顯然直接割掉 \(u,t\) 就能達(dá)到割掉 \(u,v\) 的目的而使最小割變小。
類似的可以得出 \(C_{u,v}\geq C_{u,t}\) , 那么只能是 \(C_{u,v}=C_{u,t}\)
用歸納法可以得到一個(gè) \(n\) 個(gè)點(diǎn)的圖中最多只有 \(n-1\) 個(gè)不同的最小割。

如何構(gòu)建最小割樹?

采用遞歸的策略 , 對(duì)于當(dāng)前點(diǎn)集 , 任意取兩個(gè)點(diǎn)做最小割(注意這里是對(duì)原圖跑最小割) , 然后給這兩個(gè)點(diǎn)連邊 , 權(quán)值為最小割大小。
然后就把參與網(wǎng)絡(luò)中與源點(diǎn)可達(dá)的點(diǎn)與源點(diǎn)扔在一起 , 與其他的和匯點(diǎn)扔在一起。兩邊遞歸即可。
正確性就是證明只有 \(n-1\) 個(gè)不同的最小割中的道理相同 , 考慮某一個(gè)點(diǎn)被劃分在哪個(gè)集合從而保證了正確性。

代碼:

cpp1:

#include<bits/stdc++.h> using namespace std; #define Set(a,b) memset(a,b,sizeof(a)) #define Copy(a,b) memcpy(a,b,sizeof(a)) template<class T> inline void init(T&x){x=0;char ch=getchar();bool t=0;for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') t=1;for(;ch>='0'&&ch<='9';ch=getchar()) x=(x<<1)+(x<<3)+(ch-48);if(t) x=-x; } const int M=3020; const int N=200; const int INF=2e9; struct edge{int to,next,cap,flow; }a[M<<1]; int head[N],cnt=0; int que[N],n,m; inline void add(int x,int y,int z){a[cnt]=(edge){y,head[x],z,z};head[x]=cnt++;} int d[N],S,T,cur[N]; bool bel[N];queue<int> Q; inline bool bfs(){while(!Q.empty())Q.pop();Set(d,0);d[S]=1;Q.push(S);while(!Q.empty()){int u=Q.front();Q.pop();for(int v,i=head[u];~i;i=a[i].next){v=a[i].to;if(d[v]||!a[i].cap) continue;d[v]=d[u]+1;if(v==T) return 1;Q.push(v);}}return d[T]; } int dfs(int u,int flow){if(u==T) return flow;int rest=flow;for(int v,&i=cur[u];~i;i=a[i].next){v=a[i].to;if(!a[i].cap||d[v]!=d[u]+1) continue;int f=dfs(v,min(a[i].cap,rest));if(!f) d[v]=0;rest-=f;a[i].cap-=f,a[i^1].cap+=f;if(!rest) break;}return flow-rest; } inline int Dinic(){int flow=0;while(bfs()) Copy(cur,head),flow+=dfs(S,INF);return flow; } inline void Return(){for(int i=0;i<cnt;++i) a[i].cap=a[i].flow;for(int i=1;i<=n;++i) bel[i]=0;} void Dfs(int u){bel[u]=1;for(int v,i=head[u];~i;i=a[i].next){v=a[i].to;if(a[i].cap&&!bel[v]) Dfs(v);}} namespace GHT{struct edge{int to,next,w;}a[N<<1];int head[N],cnt=0;inline void add(int x,int y,int z){a[++cnt]=(edge){y,head[x],z};head[x]=cnt;}int tmp[N];inline void Clear(){Set(head,0);cnt=0;}void Build(int l,int r){if(l>=r) return;S=que[l],T=que[r];Return();int Flow=Dinic();Dfs(S);int L=l-1,R=r+1;add(S,T,Flow),add(T,S,Flow);for(int i=l;i<=r;++i) {int u=que[i];if(bel[u]) tmp[++L]=u;else tmp[--R]=u;}for(int i=l;i<=r;++i) que[i]=tmp[i];Build(l,L),Build(R,r);return;}int gezi[N*N];inline void DFS(int u,int fa,int Mi){if(Mi!=INF) gezi[++gezi[0]]=Mi;for(int v,i=head[u];i;i=a[i].next){v=a[i].to;if(v==fa) continue;DFS(v,u,min(Mi,a[i].w));}}inline void work(){for(int i=1;i<=n;++i) que[i]=i;Build(1,n);gezi[0]=0;for(int i=1;i<=n;++i) DFS(i,0,INF);sort(gezi+1,gezi+1+gezi[0]);int q;init(q);while(q--){int x;init(x);printf("%d\n",(upper_bound(gezi+1,gezi+1+gezi[0],x)-gezi-1)/2);}puts("");return;} } int main() {int T;init(T);while(T--){Set(head,-1);cnt=0;GHT::Clear();init(n),init(m);int u,v,w;for(int i=1;i<=m;++i) {init(u),init(v),init(w);add(u,v,w),add(v,u,w);}GHT::work();}return 0; }

cpp2:

#include<bits/stdc++.h> using namespace std; #define Set(a,b) memset(a,b,sizeof(a)) #define Copy(a,b) memcpy(a,b,sizeof(a)) template<class T> inline void init(T&x){x=0;char ch=getchar();bool t=0;for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') t=1;for(;ch>='0'&&ch<='9';ch=getchar()) x=(x<<1)+(x<<3)+(ch-48);if(t) x=-x; } const int M=8501; const int N=1000; const int INF=2e9; struct edge{int to,next,cap,flow; }a[M<<1]; int head[N],cnt=0; int que[N],n,m; inline void add(int x,int y,int z){a[cnt]=(edge){y,head[x],z,z};head[x]=cnt++;} int d[N],S,T,cur[N]; bool bel[N];queue<int> Q; inline bool bfs(){while(!Q.empty())Q.pop();Set(d,0);d[S]=1;Q.push(S);while(!Q.empty()){int u=Q.front();Q.pop();for(int v,i=head[u];~i;i=a[i].next){v=a[i].to;if(d[v]||!a[i].cap) continue;d[v]=d[u]+1;if(v==T) return 1;Q.push(v);}}return d[T]; } int dfs(int u,int flow){if(u==T) return flow;int rest=flow;for(int v,&i=cur[u];~i;i=a[i].next){v=a[i].to;if(!a[i].cap||d[v]!=d[u]+1) continue;int f=dfs(v,min(a[i].cap,rest));if(!f) d[v]=0;rest-=f;a[i].cap-=f,a[i^1].cap+=f;if(!rest) break;}return flow-rest; } inline int Dinic(){int flow=0;while(bfs()) Copy(cur,head),flow+=dfs(S,INF);return flow; } inline void Return(){for(int i=0;i<cnt;++i) a[i].cap=a[i].flow;for(int i=1;i<=n;++i) bel[i]=0;} void Dfs(int u){bel[u]=1;for(int v,i=head[u];~i;i=a[i].next){v=a[i].to;if(a[i].cap&&!bel[v]) Dfs(v);}} namespace GHT{struct edge{int to,next,w;}a[N<<1];int head[N],cnt=0;inline void add(int x,int y,int z){a[++cnt]=(edge){y,head[x],z};head[x]=cnt;}int tmp[N];void Build(int l,int r){if(l>=r) return;S=que[l],T=que[r];Return();int Flow=Dinic();Dfs(S);int L=l-1,R=r+1;add(S,T,Flow),add(T,S,Flow);for(int i=l;i<=r;++i) {int u=que[i];if(bel[u]) tmp[++L]=u;else tmp[--R]=u;}for(int i=l;i<=r;++i) que[i]=tmp[i];Build(l,L),Build(R,r);return;}map<int,int>vis;int ans=0;inline void DFS(int u,int fa,int Mi){if(Mi!=INF) {if(!vis.count(Mi)) vis[Mi]=1,++ans;}for(int v,i=head[u];i;i=a[i].next){v=a[i].to;if(v==fa) continue;DFS(v,u,min(Mi,a[i].w));}}inline void work(){for(int i=1;i<=n;++i) que[i]=i;Build(1,n);for(int i=1;i<=n;++i) DFS(i,0,INF);cout<<ans<<endl;return;} } int main() {Set(head,-1);init(n),init(m);int u,v,w;for(int i=1;i<=m;++i) {init(u),init(v),init(w);add(u,v,w),add(v,u,w);}GHT::work();return 0; }

轉(zhuǎn)載于:https://www.cnblogs.com/NeosKnight/p/10443948.html

總結(jié)

以上是生活随笔為你收集整理的【LuoguP33294123】[ZJOI2011]最小割[CQOI2016]不同的最小割的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。