您的位置:首页 > 其它

2017.9.1 最小生成树 失败总结

2017-09-01 21:03 344 查看
这题还是挺好的、就是有一点绕

一开始只想到要删去选定边两个顶点相连的边,然后再if删除,但这样是错误的

其实一个边在不在最小生成树里就只要看有没有一条路径能全走比他小的边,使得这条边的两个点联通就好了

因为如果有一条路径中出现了比他小的边,,那这个边就可以选,当前边就可以断开,至少会比使用当前边会小

或者从kruskal算法的原理,如果比他小的边联通了这两个点,那这个边一定不会被选到

最大生成树同理,,

所以就相当于断掉最少的边,使u到v没有一条除选定边以外的路径

最 小 割



#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
#define inf 1000000007
#define N 800005
queue<int>q;
int tot=-1,n,m,dis
,hou
,xia
,zhi
,zhong
,x,y,z,daan,yuan
,s,t,a
,b
,c
,l;
void jian(int x,int y,int z)
{
++tot,hou[tot]=yuan[x],yuan[x]=tot,zhi[tot]=z,zhong[tot]=y;
}
void jia(int x,int y,int z)
{
jian(x,y,z);
jian(y,x,z);
}
bool bfs(int s,int t)
{
for(int i=1;i<=n;i++)
{
dis[i]=1000000009;
xia[i]=yuan[i];
}
dis[s]=0;
q.push(s);
while(!q.empty())
{
int st=q.front();
q.pop();
for(int i=xia[st];i!=-1;i=hou[i])
{
int nd=zhong[i];
if(dis[nd]>inf&&zhi[i]>0)
{
dis[nd]=dis[st]+1;
q.push(nd);
}
}
}
return dis[t]<inf;
}
int dfs(int o,int t,int limit)
{
if(limit==0||t==o)return limit;
int f=0,i,nd,flow=0;
for(i=xia[o];i!=-1;i=hou[i])
{
xia[o]=i;
nd=zhong[i];
if(dis[nd]==dis[o]+1&&(f=dfs(nd,t,min(zhi[i],limit))))
{
limit-=f;
flow+=f;
zhi[i]-=f;
zhi[i^1]+=f;
if(limit==0)break;
}
}
return flow;
}
int dinic(int s,int t)
{
int ans=0;
while(bfs(s,t))
{
ans+=dfs(s,t,inf);
}
return ans;
}
int main()
{
int i;
scanf("%d%d",&n,&m);
for(i=1;i<=m;i++)
{
scanf("%d%d%d",&a[i],&b[i],&c[i]);
}
scanf("%d%d%d",&s,&t,&l);
memset(yuan,-1,sizeof(yuan));
tot=-1;
for(i=1;i<=m;i++)
{
if(c[i]<l)jia(a[i],b[i],1);
}
daan+=dinic(s,t);
memset(yuan,-1,sizeof(yuan));
tot=-1;
for(i=1;i<=m;i++)
{
if(c[i]>l)jia(a[i],b[i],1);
}
daan+=dinic(s,t);
printf("%d",daan);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: