2016计蒜之道复赛 菜鸟物流的运输网络 网络流EK

题源:https://nanti.jisuanke.com/t/11215

分析:这题是一个比较经典的网络流模型。把中间节点当做源,两端节点当做汇,对节点进行拆点,做一个流量为 22 的流即可。

吐槽:这是官方题解,然后其实赛场上谢了这个解法,但是我写搓了,因为最后输出路径的时候傻逼了

        我居然向最短路一样记录前驱输出路径,简直傻逼了

        着重强调(对我自己):网络流的一次增广是需要记录前驱的,但是多次增广以后,可以反向流,前驱就不对了

        所以要判断哪些边,在最大流上时,需要枚举边,看哪个满流,然后随便搞搞

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <string>
#include <stack>
#include <vector>
#include <map>
#include <queue>
#include <algorithm>
#include <utility>
using namespace std;
typedef long long LL;
const int N=505;
const int INF=0x3f3f3f3f;
int cap[N][N],flow[N][N],n,m,s,t;
bool vis[N];
int p[N],a[N];
void maxflow(int s,int t){
    queue<int>q;
    memset(flow,0,sizeof(flow));
    while(1){
        memset(a,0,sizeof(a));
        memset(vis,false,sizeof(vis));
        while(!q.empty())q.pop();
        a[s]=INF;q.push(s);
        while(!q.empty()){
            int u=q.front();q.pop();
            if(u==t)break;
            for(int v=0;v<=n*2+1;++v)
              if(!a[v]&&flow[u][v]<cap[u][v]){
                vis[v]=true;
                p[v]=u;a[v]=min(a[u],cap[u][v]-flow[u][v]);
                q.push(v);  
              }
        }
        if(!a[t])break;
        for(int u=t;u!=s;u=p[u]){
            flow[p[u]][u]+=a[t];
            flow[u][p[u]]-=a[t];
        }
    }
}
struct Edge{
  int v,next;
}edge[105*105];
int head[105],tot;
void add(int u,int v){
  edge[tot].v=v;
  edge[tot].next=head[u];
  head[u]=tot++;
}
vector<int>ret;
void dfs(int u,int f){
  ret.push_back(u);
  for(int i=head[u];~i;i=edge[i].next){
    int v=edge[i].v;
    if(v==f)continue;
    dfs(v,u);
  }
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--){
      int a,b,mid;
      scanf("%d%d%d%d%d",&n,&m,&a,&b,&mid);
      s=0,t=n*2+1;
      memset(cap,0,sizeof(cap));
      for(int i=0;i<m;++i){
        int u,v;
        scanf("%d%d",&u,&v);
        cap[u+n][v]=cap[v+n][u]=1;
      }
      for(int i=1;i<=n;++i)
        cap[i][i+n]=1;
      cap[s][mid]=cap[mid][mid+n]=2;
      cap[a+n][t]=cap[b+n][t]=1;
      maxflow(s,t);
      memset(head,-1,sizeof(head));tot=0;
      for(int i=1+n;i<=n+n;++i){
        if(!flow[i-n][i])continue;
        for(int j=1;j<=n;++j){
          if(cap[i][j]&&flow[i][j]==cap[i][j]){
             add(i-n,j);add(j,i-n);
          }
        }
      }
      ret.clear();
      dfs(a,0);
      for(int i=0;i<ret.size();++i){
         printf("%d",ret[i]);
         if(i+1==ret.size())printf("\n");
         else printf(" ");
      }
    }
    return 0;
}
View Code

 

 

posted @ 2016-07-03 22:43  shuguangzw  阅读(427)  评论(0编辑  收藏  举报