您的位置:首页 > 其它

【bzoj2561】【最小生成树】【最小割】

2016-03-28 21:55 246 查看

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;

  数据保证图中没有自环。

 

Output

 输出一行一个整数表示最少需要删掉的边的数量。

Sample Input

3 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。
题解:考虑一条边存在于最小生成树里,
           如果删去这条边,剩下的比它权值小的边中一定不能使这条边的两端点联通。
           所以我们把比它权值小的边都建成一个网络。
           从这条边的一个端点向另一个端点跑最大流即可。
           最小割即是答案。
           最大生成树同理。
代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define N 20010
#define M 2000010
#define INF 2100000000
using namespace std;
int point
,x,y,next[M*2],cnt(1),n,m,ans1,ans2,l;
int cur
,pre
,dis
,gap
,T,t;
bool f;
struct use{int st,en,v;}e[M*2];
struct use2{int st,en,v;}b[M*2];
bool cmp1(use2 a,use2 b){return a.v<b.v;}
bool cmp2(use2 a,use2 b){return a.v>b.v;}
void add(int x,int y,int v){
//cout<<x<<' '<<y<<endl;
next[++cnt]=point[x];point[x]=cnt;e[cnt].st=x;e[cnt].en=y;e[cnt].v=v;
next[++cnt]=point[y];point[y]=cnt;e[cnt].st=y;e[cnt].en=x;e[cnt].v=v;
}
int isap(int ss,int en){
int i,mn,u(ss),ans(0);
memset(gap,0,sizeof(gap));
memset(dis,0,sizeof(dis));
gap[0]=T;
for (i=1;i<=T;i++) cur[i]=point[i];
while(dis[ss]<T){
f=false;
for (i=cur[u];i;i=next[i])
if (dis[e[i].en]+1==dis[u]&&e[i].v){cur[u]=i;f=true;break;}
if (f){
pre[u=e[i].en]=i;
if (u==en){
mn=INF;
for (i=en;i!=ss;i=e[pre[i]].st) mn=min(mn,e[pre[i]].v);
ans+=mn;
for (i=en;i!=ss;i=e[pre[i]].st) e[pre[i]].v-=mn,e[pre[i]^1].v+=mn;
u=ss;
}
}
else{
gap[dis[u]]--;if (!gap[dis[u]])return ans;
for (mn=T,i=point[u];i;i=next[i]) if (e[i].v)mn=min(mn,dis[e[i].en]);
++gap[dis[u]=mn+1];cur[u]=point[u];if (u!=ss) u=e[pre[u]].st;
}
}
return ans;
}
int main(){
scanf("%d%d",&n,&m);T=n;
for (int i=1;i<=m;i++) scanf("%d%d%d",&b[i].st,&b[i].en,&b[i].v);
scanf("%d%d%d",&x,&y,&l);sort(b+1,b+m+1,cmp1);t=1;
while(b[t].v<l&&t<=m){add(b[t].st,b[t].en,1),t++;}
ans1=isap(x,y);
memset(point,0,sizeof(point));cnt=1;
sort(b+1,b+m+1,cmp2);t=1;
while(b[t].v>l&&t<=m){add(b[t].st,b[t].en,1);t++;}
ans2=isap(x,y);
cout<<ans1+ans2<<endl;
}

           
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: