bzoj2561: 最小生成树(最小割)
https://www.lydsy.com/JudgeOnline/problem.php?id=2561
考虑Kruscal算法求最小生成树的流程
如果 u和v之间的长为L的边能出现在最小生成树里,说明<L的边不能时u和v联通
即求图中只存在<L的边时,u和v的最小割
如果 u和v之间的长为L的边能出现在最大生成树里,说明>L的边不能时u和v联通
即求图中只存在>L的边时,u和v的最小割
#include<cstdio> #include<queue> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define N 20001 #define M 200001 int n,m; int tot; int src,decc; int front[N],to[M<<1],nxt[M<<1],cap[M<<1]; int lev[N],cur[N]; queue<int>q; struct node { int u,v,l; }e[M]; void read(int &x) { x=0; char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); } } bool bfs() { for(int i=0;i<=n;++i) cur[i]=front[i],lev[i]=-1; while(!q.empty()) q.pop(); q.push(src); lev[src]=0; int now,t; while(!q.empty()) { now=q.front(); q.pop(); for(int i=front[now];i;i=nxt[i]) { t=to[i]; if(lev[t]==-1 && cap[i]) { lev[t]=lev[now]+1; if(t==decc) return true; q.push(t); } } } return false; } int dinic(int now,int flow) { if(now==decc) return flow; int rest=0,delta; for(int &i=cur[now];i;i=nxt[i]) if(cap[i] && lev[to[i]]==lev[now]+1) { delta=dinic(to[i],min(flow-rest,cap[i])); if(delta) { rest+=delta; cap[i]-=delta; cap[i^1]+=delta; if(rest==flow) break; } } if(rest!=flow) lev[now]=-1; return rest; } bool cmp1(node p,node q) { return p.l<q.l; } bool cmp2(node p,node q) { return p.l>q.l; } void add(int u,int v,int w) { to[++tot]=v; nxt[tot]=front[u]; front[u]=tot; cap[tot]=w; to[++tot]=u; nxt[tot]=front[v]; front[v]=tot; cap[tot]=w; } int main() { read(n); read(m); for(int i=1;i<=m;++i) read(e[i].u),read(e[i].v),read(e[i].l); read(src); read(decc); int L; read(L); int ans=0; tot=1; sort(e+1,e+m+1,cmp1); for(int i=1;i<=m;++i) if(e[i].l>=L) break; else add(e[i].u,e[i].v,1); while(bfs()) ans+=dinic(src,2e9); memset(front,0,sizeof(front)); tot=1; sort(e+1,e+m+1,cmp2); for(int i=1;i<=m;++i) if(e[i].l<=L) break; else add(e[i].u,e[i].v,1); while(bfs()) ans+=dinic(src,2e9); printf("%d",ans); }