2017.9.1 最小生成树 失败总结

xiaoxiao2021-02-28  89

这题还是挺好的、就是有一点绕

一开始只想到要删去选定边两个顶点相连的边,然后再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[N],hou[N],xia[N],zhi[N],zhong[N],x,y,z,daan,yuan[N],s,t,a[N],b[N],c[N],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); }

转载请注明原文地址: https://www.6miu.com/read-96076.html

最新回复(0)