• 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("
    ");
             else printf(" ");
          }
        }
        return 0;
    }
    View Code

     

  • 相关阅读:
    mongodb的索引
    mongodb的简单操作
    mongodb的安装
    redis简单消息队列
    支持utf8的str_split函数
    php curl 传递数据
    linux 安装 ftp
    php des 对称加解密类
    13. Roman to Integer
    12. Integer to Roman
  • 原文地址:https://www.cnblogs.com/shuguangzw/p/5639049.html
Copyright © 2020-2023  润新知