【BZOJ】【2561】最小生成树
网络流/最小割
对于所有小于L的边求一个割使得U,V不连通,这样就可以保证L可能在最小生成树里。
最大生成树同理。
答案累加一下即可。(Orz Hzwer)
(我一开始怎么会sb地去想到一起求呢……)
1 /************************************************************** 2 Problem: 2561 3 User: Tunix 4 Language: C++ 5 Result: Accepted 6 Time:884 ms 7 Memory:15340 kb 8 ****************************************************************/ 9 10 //BZOJ 2561 11 #include<cstdio> 12 #include<cstring> 13 #include<algorithm> 14 #define rep(i,n) for(int i=0;i<n;++i) 15 #define F(i,j,n) for(int i=j;i<=n;++i) 16 #define D(i,j,n) for(int i=j;i>=n;--i) 17 using namespace std; 18 inline int getint(){ 19 int v=0,sign=1; char ch=getchar(); 20 while(ch<'0'||ch>'9'){ if (ch=='-') sign=-1; ch=getchar();} 21 while(ch>='0'&&ch<='9'){ v=v*10+ch-'0'; ch=getchar();} 22 return v*sign; 23 } 24 const int N=30010,M=1000010,INF=~0u>>2; 25 typedef long long LL; 26 /******************tamplate*********************/ 27 int n,m,l,ans,x[200010],y[200010],v[200010]; 28 struct edge{int to,v;}; 29 struct Net{ 30 edge E[M]; 31 int head[N],next[M],cnt; 32 void ins(int x,int y,int v){ 33 E[++cnt]=(edge){y,v}; 34 next[cnt]=head[x]; head[x]=cnt; 35 } 36 void add(int x,int y,int v){ 37 ins(x,y,v); ins(y,x,v); 38 } 39 int s,t,cur[N],d[N],Q[N]; 40 void init(){ 41 n=getint(); m=getint();cnt=1; 42 memset(head,0,sizeof head); 43 F(i,1,m){ 44 x[i]=getint(); y[i]=getint(); v[i]=getint(); 45 } 46 s=getint(); t=getint(); l=getint(); ans=0; 47 48 F(i,1,m) if (v[i]<l) add(x[i],y[i],1); 49 Dinic(); 50 cnt=1; memset(head,0,sizeof (head)); 51 F(i,1,m) if (v[i]>l) add(x[i],y[i],1); 52 Dinic(); 53 printf("%d\n",ans); 54 } 55 bool mklevel(){ 56 memset(d,-1,sizeof d); 57 d[s]=0; 58 int l=0,r=-1; 59 Q[++r]=s; 60 while(l<=r){ 61 int x=Q[l++]; 62 for(int i=head[x];i;i=next[i]) 63 if (d[E[i].to]==-1 && E[i].v){ 64 d[E[i].to]=d[x]+1; 65 Q[++r]=E[i].to; 66 } 67 } 68 return d[t]!=-1; 69 } 70 int dfs(int x,int a){ 71 if (x==t) return a; 72 int flow=0; 73 for(int &i=cur[x];i && flow<a;i=next[i]) 74 if (E[i].v && d[E[i].to]==d[x]+1){ 75 int f=dfs(E[i].to,min(a-flow,E[i].v)); 76 E[i].v-=f; 77 E[i^1].v+=f; 78 flow+=f; 79 } 80 if (!flow) d[x]=-1; 81 return flow; 82 } 83 void Dinic(){ 84 while(mklevel()){ 85 F(i,1,n) cur[i]=head[i]; 86 ans+=dfs(s,INF); 87 } 88 } 89 }G1; 90 91 int main(){ 92 #ifndef ONLINE_JUDGE 93 freopen("2561.in","r",stdin); 94 freopen("2561.out","w",stdout); 95 #endif 96 G1.init(); 97 return 0; 98 }
2561: 最小生成树
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 873 Solved: 435
[Submit][Status][Discuss]
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。