bzoj2561 最小生成树
Description
给定一个边带正权的连通无向图G=(V,E),其中N=|V|,M=|E|,N个点从1到N依次编号,给定三个正整数u,v,和L (u≠v),假设现在加入一条边权为L的边(u,v),那么需要删掉最少多少条边,才能够使得这条边既可能出现在最小生成树上,也可能出现在最大生成树上?
Input
第一行包含用空格隔开的两个整数,分别为N和M;
接下来M行,每行包含三个正整数u,v和w表示图G存在一条边权为w的边(u,v)。
最后一行包含用空格隔开的三个整数,分别为u,v,和 L;
数据保证图中没有自环。
接下来M行,每行包含三个正整数u,v和w表示图G存在一条边权为w的边(u,v)。
最后一行包含用空格隔开的三个整数,分别为u,v,和 L;
数据保证图中没有自环。
Output
输出一行一个整数表示最少需要删掉的边的数量。
Sample Input
3 2
3 2 1
1 2 3
1 2 2
3 2 1
1 2 3
1 2 2
Sample Output
1
HINT
对于20%的数据满足N ≤ 10,M ≤ 20,L ≤ 20;
对于50%的数据满足N ≤ 300,M ≤ 3000,L ≤ 200;
对于100%的数据满足N ≤ 20000,M ≤ 200000,L ≤ 20000。
正解:最小割。
讲道理这题并不难,但是我完全没往最小割那方面去想,于是做不出。。
我们知道,要使$(u,v,w)$在最小生成树上,必须割掉边权小于$w$的一些边,使得$u,v$不连通,最大生成树同理。
于是我们对于小于$w$的边连起来,跑一遍最小割,大于$w$的同理。两个最小割加起来,就是答案了。
1 //It is made by wfj_2048~ 2 #include <algorithm> 3 #include <iostream> 4 #include <cstring> 5 #include <cstdlib> 6 #include <cstdio> 7 #include <vector> 8 #include <cmath> 9 #include <queue> 10 #include <stack> 11 #include <map> 12 #include <set> 13 #define inf (1<<30) 14 #define N (500010) 15 #define il inline 16 #define RG register 17 #define ll long long 18 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout) 19 20 using namespace std; 21 22 struct edge{ int nt,to,flow,cap; }g[N]; 23 struct E{ int u,v,w; }e[N]; 24 25 int head[N],d[N],q[N],n,m,u,v,w,num,ans; 26 27 il int gi(){ 28 RG int x=0,q=1; RG char ch=getchar(); 29 while ((ch<'0' || ch>'9') && ch!='-') ch=getchar(); 30 if (ch=='-') q=-1,ch=getchar(); 31 while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); 32 return q*x; 33 } 34 35 il void insert(RG int from,RG int to,RG int cap){ 36 g[++num]=(edge){head[from],to,0,cap},head[from]=num; return; 37 } 38 39 il int cmp(const E &a,const E &b){ return a.w<b.w; } 40 41 il int bfs(RG int S,RG int T){ 42 memset(d,0,sizeof(d)); 43 RG int h=0,t=1; q[t]=S,d[S]=1; 44 while (h<t){ 45 RG int x=q[++h],v; 46 for (RG int i=head[x];i;i=g[i].nt){ 47 v=g[i].to; 48 if (!d[v] && g[i].cap>g[i].flow){ 49 d[v]=d[x]+1,q[++t]=v; 50 if (v==T) return 1; 51 } 52 } 53 } 54 return 0; 55 } 56 57 il int dfs(RG int x,RG int T,RG int a){ 58 if (x==T || !a) return a; RG int v,f,flow=0; 59 for (RG int i=head[x];i;i=g[i].nt){ 60 v=g[i].to; 61 if (d[v]==d[x]+1 && g[i].cap>g[i].flow){ 62 f=dfs(v,T,min(a,g[i].cap-g[i].flow)); 63 if (!f){ d[v]=-1; continue; } 64 g[i].flow+=f,g[i^1].flow-=f; 65 flow+=f,a-=f; if (!a) break; 66 } 67 } 68 return flow; 69 } 70 71 il int maxflow(RG int S,RG int T){ 72 RG int flow=0; 73 while (bfs(S,T)) flow+=dfs(S,T,inf); 74 return flow; 75 } 76 77 il void work(){ 78 n=gi(),m=gi(); 79 for (RG int i=1;i<=m;++i) e[i].u=gi(),e[i].v=gi(),e[i].w=gi(); 80 u=gi(),v=gi(),w=gi(),sort(e+1,e+m+1,cmp),num=1; 81 for (RG int i=1;i<=m;++i){ 82 if (e[i].w>=w) break; 83 insert(e[i].u,e[i].v,1),insert(e[i].v,e[i].u,1); 84 } 85 ans+=maxflow(u,v),memset(head,0,sizeof(head)),num=1; 86 for (RG int i=m;i;--i){ 87 if (e[i].w<=w) break; 88 insert(e[i].u,e[i].v,1),insert(e[i].v,e[i].u,1); 89 } 90 ans+=maxflow(u,v); printf("%d\n",ans); return; 91 } 92 93 int main(){ 94 File("tree"); 95 work(); 96 return 0; 97 }