本题需要用一点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;
}