网络流学习总结

最近在老师的带领下学习了网络流,认真的搞啊搞,终于懂了基础模板

先上一发dinic(没有带当前弧优化哦)不过看者还是挺快的;

#include<queue>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=1001010;
const int INF=1e9;
int m,n,s,t,cnt=-1,head[N],ans,dep[N];
struct edge
{ int to,nx,flow;} e[N];
void add_edge(int u,int v,int w)
{ cnt++;
  e[cnt].to=v;
  e[cnt].flow=w;
  e[cnt].nx=head[u];
  head[u]=cnt;
}
bool bfs(int s,int t)
{ queue<int> que;
  memset(dep,0,sizeof(dep));
  dep[s]=1;que.push(s);
  while (!que.empty())
  { int x=que.front();que.pop();
    for (int i=head[x];i!=-1;i=e[i].nx)
    { int y=e[i].to;
      if (dep[y]==0&&e[i].flow>0)
      { dep[y]=dep[x]+1;
        que.push(y);
      }
    }
  }
  if (dep[t]>0) return true;
  else return false;
}
int dfs(int x,int limit,int t)
{ if (x==t) return limit;
  for (int i=head[x];i!=-1;i=e[i].nx)
  { int y=e[i].to;
    if (dep[y]==dep[x]+1&&e[i].flow>0)
    { int di=dfs(y,min(limit,e[i].flow),t);
      if (di>0)
      { e[i].flow-=di;
        e[i^1].flow+=di;
        return di;
      }
    }
  }
  return 0;
}
void dinic(int s,int t)
{  while (bfs(s,t)) ans+=dfs(s,INF,t);
}
int main()
{ freopen("ditch.in","r",stdin);
  freopen("ditch.out","w",stdout);
  scanf("%d%d",&m,&n);
  memset(head,-1,sizeof(head));
  for (int i=1;i<=m;i++)
  { int x,y,z;
    scanf("%d%d%d",&x,&y,&z);
    add_edge(x,y,z);
    add_edge(y,x,0); 
  }
  dinic(1,n);
  printf("%d",ans);
  return 0;
}

用的是草地排水这道题来作例子,其实模板啥的,看懂思路背一背就好了

然后就是最小费用最大流

洛谷的模板

#include<bits/stdc++.h>
using namespace std;
const int N=100010;
const int INF=0x7fffffff;
int dis[N],flow[N],cnt=-1,head[N],m,n,s,t,pre[N],last[N],mincost,maxflow;
bool inque[N];
struct edge
{ int to,nx,dist,flow;} e[N];
void add_edge(int u,int v,int w,int f)
{ cnt++;
  e[cnt].flow=w;
  e[cnt].dist=f;
  e[cnt].to=v;
  e[cnt].nx=head[u];
  head[u]=cnt;
}
bool SPFA(int s,int t)
{ for (int i=1;i<=N;i++) dis[i]=INF;
  for (int i=1;i<=N;i++) flow[i]=INF;
  memset(inque,0,sizeof(inque));
  queue<int> que;que.push(s);inque[s]=true;pre[t]=-1;dis[s]=0;
  while (!que.empty())
  { int x=que.front();que.pop();inque[x]=false;
    for (int i=head[x];i!=-1;i=e[i].nx)
    { int y=e[i].to;
      if (dis[y]>dis[x]+e[i].dist&&e[i].flow>0)
      { dis[y]=dis[x]+e[i].dist;
        pre[y]=x;
        last[y]=i;
        flow[y]=min(flow[x],e[i].flow);
        if (!inque[y])
        { que.push(y);inque[y]=true;} 
      }
    }
   }
  if (pre[t]==-1) return false;
  else return true; 
}
void MCMF(int s,int t)
{ while (SPFA(s,t))
  { int x=t;
    maxflow+=flow[t];
    mincost+=dis[t]*flow[t];
    while (x!=s)
    { e[last[x]].flow-=flow[t];
      e[last[x]^1].flow+=flow[t];
      x=pre[x];
    }
  }
}
int main()
{ scanf("%d%d%d%d",&n,&m,&s,&t);
  memset(head,-1,sizeof(head));
  for (int i=1;i<=m;i++)
  { int x,y,z,f;
    scanf("%d%d%d%d",&x,&y,&z,&f);
    add_edge(x,y,z,f);add_edge(y,x,0,-f);
  }
  MCMF(s,t);
  printf("%d  %d",maxflow,mincost);
  return 0;
}

进入今天的正题,追查坏牛奶

思想的话不会人家的玄学求最小割的边数,于是自己想了个神奇的乱搞,先求出最大流,即最小割,然后枚举每条边看是否完全属于割集,然后将其永久去掉

然后将整个输出即可,代码纯属原创

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=100010;
const ll INF=0x7ffffffff;
ll m,n,s,t,pre[N],head[N],cnt=1,last[N],dep[N],tot,sum[N],ans,Ans,ff;
struct edge
{ ll from,to,nx,flow;} e[N];
struct node
{ ll x,y,z;} kk[N];
void add_edge(ll from,ll to,ll flow)
{ cnt++;e[cnt].from=from;e[cnt].flow=flow;
  e[cnt].nx=head[from];e[cnt].to=to;head[from]=cnt;
  cnt++;e[cnt].flow=0;e[cnt].to=from;
  e[cnt].from=to;e[cnt].nx=head[to];head[to]=cnt;
}
bool bfs(int s,int t)
{ memset(dep,0,sizeof(dep));
  queue<ll> que;dep[s]=1;que.push(s);
  while (!que.empty())
  { ll x=que.front();que.pop();
    for (ll i=head[x];i;i=e[i].nx)
    { ll y=e[i].to;
      if (dep[y]==0&&e[i].flow>0)
      { dep[y]=dep[x]+1;
        que.push(y);
      }
    }
  }
 if (dep[t]==0) return false;
 else return true;  
}
ll dfs(int x,ll limit,int t)
{ if(x==t) return limit;
  ll used=0;
  for (ll i=head[x];i;i=e[i].nx)
  { ll y=e[i].to;
    if (dep[y]==dep[x]+1&&e[i].flow>0)
    { ll di=dfs(y,min(limit-used,e[i].flow),t);
      if (di>0)
      { e[i].flow-=di;
        e[i^1].flow+=di;
        used+=di;
        if (used==limit) return used;
      }
    }
  }
 if (!used) dep[x]=-2;
 return used; 
}
void dinic()
{ while (bfs(1,n)) ans+=dfs(1,INF,n);}
void cs()
{  ans=0;cnt=1;memset(head,0,sizeof(head));
   for (int j=1;j<=m;j++) add_edge(kk[j].x,kk[j].y,kk[j].z);
   for (int k=1;k<=tot;k++) {e[sum[k]*2].flow=0;} 
}
int main()
{ 
  scanf("%lld%lld",&n,&m);
  for (ll i=1;i<=m;i++)
  { ll x,y,z;
    scanf("%lld%lld%lld",&x,&y,&z);
    kk[i].x=x;kk[i].y=y;kk[i].z=z;
    add_edge(x,y,z);
  }
  dinic();ff=ans;Ans=ans;
  for (int i=1;i<=m;i++)
  { cs();
    ll f=e[i*2].flow;
    e[i*2].flow=0;
    dinic();
    if (ans==0&&f==ff) {tot=1;sum[tot]=i;break;}
    if (ans+f==Ans) {tot++;sum[tot]=i;Ans=ans;}
  }
  printf("%lld %lld ",ff,tot);
  for (int i=1;i<=tot;i++)
  printf("%lld ",sum[i]);
  return 0;
}

hale会越来越棒的

猜你喜欢

转载自www.cnblogs.com/Hale522520/p/10392243.html