BZOJ 2561 - 最小生成树 + 最小割
本题需要用一点M(in & ax)ST的性质。。
以MinestST(这英语也是十级水平。。)为例。。假设加入边(u, v),边权为L。然后我们把所有边权小于L的边都取出来单独看。这些边不能连通u, v,否则(u,v)边绝无可能在MST中——因为在加入它之后形成的这个环中,如果去掉它,显然是最优的。
所以以u、v为s、t,每条边权小于L的边容量置为1、跑一遍无向图最小割即可。。
MaxestST同理。。答案只需两次相加(因为不会统计到重复的边)。。
武神提了一个问题。。竟被吓到。。无向图最小割是什么鬼!
怎么建图?难道要拆成两个方向建四条弧!?
不用。。只要建一个方向。。因为两个方向上不可能有同时有流量。。
Solved...
// BZOJ 2561 #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int N=20000+5, M=200000*2+5, INF=0x7f7f7f7f; #define rep(i,a,b) for (int i=a; i<=b; i++) #define dep(i,a,b) for (int i=a; i>=b; i--) #define read(x) scanf("%d", &x) #define fill(a,x) memset(a, x, sizeof(a)) struct Edge { int from, to, dis; bool operator < (const Edge &x) const { return dis<x.dis; } } e[M/2]; struct Graph { int s, from[M], to[M], cap[M], pre[M], last[N]; void init() { s=-1; fill(last, -1); } void ine(int a, int b, int c) { s++; from[s]=a, to[s]=b, cap[s]=c, pre[s]=last[a]; last[a]=s; } void ine2(int a, int b, int c1, int c2) { ine(a, b, c1); ine(b, a, c2); } } G; #define reg(i,s,u) for (int i=s.last[u]; i!=-1; i=s.pre[i]) int Q[N*4], d[N], cur[N], n, m, u, v, w; bool vis[N]; bool BFS(int s, int t) { int head=1, tail=1; fill(vis, false); Q[1]=s; d[s]=0; vis[s]=true; while (head<=tail) { int x=Q[head++]; reg(i,G,x) { int y=G.to[i]; if (G.cap[i]<=0 || vis[y]) continue; vis[y]=true; d[y]=d[x]+1; Q[++tail]=y; } } return vis[t]; } int DFS(int x, int t, int a) { if (x==t || a==0) return a; int ret=0, flow; for (int &i=cur[x]; i!=-1; i=G.pre[i]) { int y=G.to[i]; if (d[y]==d[x]+1 && (flow=DFS(y, t, min(a, G.cap[i])))>0) { G.cap[i]-=flow; G.cap[i^1]+=flow; a-=flow; ret+=flow; if (a==0) break; // 这个break不能往前写! } } return ret; } int Dinic(int s, int t) { int ret=0; while (BFS(s, t)) { rep(i,1,n) cur[i]=G.last[i]; ret+=DFS(s, t, INF); } return ret; } int main() { read(n); read(m); rep(i,1,m) read(e[i].from), read(e[i].to), read(e[i].dis); int ans=0; sort(e+1, e+m+1); read(u), read(v), read(w); G.init(); rep(i,1,m) if (e[i].dis<w) G.ine2(e[i].from, e[i].to, 1, 1); else break; ans+=Dinic(u, v); G.init(); dep(i,m,1) if (e[i].dis>w) G.ine2(e[i].from, e[i].to, 1, 1); else break; ans+=Dinic(u, v); printf("%d\n", ans); return 0; }