zoukankan      html  css  js  c++  java
  • 航空路线问题

    最大费用最大流。
    建图思路:
    起点终点能走两次,限流。
    用个map存下string与编号的对应关系,输出方案时走那些走过流量的边。

    #include <iostream>
    #include <cstdio>
    #include <string>
    #include <cstring>
    #include <queue>
    #include <map>
    using namespace std;
    const int N=1005,inf=0x3f3f3f3f;
    map<string,int> mp;
    bool check;
    int n,v,S,T;
    string s,b,bpw[N];
    int k,head[N],ecnt=1,l[N],r[N],from[N],maxflow,mincost,dis[N],opt[2][N],tot[2];
    bool inq[N];
    struct Edge {
         int to,nxt,val,cost,from;
    } e[N*N*2];
    void add(int bg,int ed,int val,int cost) {
         e[++ecnt].cost=cost;
         e[ecnt].from=bg;
         e[ecnt].nxt=head[bg];
         e[ecnt].to=ed;
         e[ecnt].val=val;
         head[bg]=ecnt;
    }
    void insert(int bg,int ed,int val,int cost) {
         cost=-cost;
         add(bg,ed,val,cost);
         add(ed,bg,0,-cost);
    }
    queue<int>qu;
    bool spfa() {
         qu.push(S);
         std::memset(dis,0x3f,sizeof dis);
         dis[S]=0;
         inq[S]=1;
         while(!qu.empty()) {
             int u=qu.front();
             qu.pop();
             inq[u]=0;
             for(int i=head[u],v; i; i=e[i].nxt) {
                 v=e[i].to;
                 if(dis[v]>dis[u]+e[i].cost&&e[i].val) {
                     dis[v]=dis[u]+e[i].cost;
                     from[v]=i;
                     if(!inq[v]) qu.push(v),inq[v]=1;
                 }
             }
         }
         return dis[T]!=inf;
    }
    void min(int &x,int y) {
         x=x<y?x:y;
    }
    void mcf() {
         int x=inf,i=from[T];
         while(i) {
             min(x,e[i].val);
             i=from[e[i].from];
         }
         maxflow+=x;
         i=from[T];
         while(i) {
             e[i].val-=x;
             e[i^1].val+=x;
             mincost-=x*e[i].cost;
             i=from[e[i].from];
        }
    }
    void dfs(int x,int op) {
      opt[op][++tot[op]]=x;
      for(int i=head[x];i;i=e[i].nxt) {
        int v=e[i].to;
        if(i&1) continue;
        if(e[i^1].val) {
          e[i^1].val--;
          dfs(v,op);
          return;
        }
      }
    }
    int main() {
       scanf("%d%d",&n,&v);
       S=0,T=2*n+1;
       for(int i=1;i<=n;i++) cin>>s,mp[s]=i,bpw[i]=s;
       insert(S,1,2,0);
       insert(n<<1,T,2,0);
       insert(1,1+n,2,1);
       insert(n,n+n,2,1);
       for(int i=2;i<n;i++)
         insert(i,i+n,1,1);
       for(int i=1;i<=v;i++){
         cin>>s>>b;
         int st=mp[s],ed=mp[b];
         if(st<ed)insert(st+n,ed,1,0);
         else insert(ed+n,st,inf,0);
       }
       while(spfa()) mcf();
       if(!maxflow) {puts("No Solution!");return 0;}
       if(maxflow==1) {cout<<2<<endl<<bpw[1]<<endl<<bpw[n]<<endl<<bpw[1];return 0;}
       cout<<mincost-2<<endl;
       dfs(1,0),dfs(1,1);
       bool flag=0;
       for(int i=1;i<=tot[0];i++) if(opt[0][i]>=1&&opt[0][i]<=n) cout<<bpw[opt[0][i]]<<endl;
       for(int i=tot[1];i;i--) {
         if(opt[1][i]>=1&&opt[1][i]<=n) {
          if(!flag) {
            flag=1;
            continue;
          }
          cout<<bpw[opt[1][i]]<<endl;
         }
       }
       return 0;
    }
    
    我是咸鱼。转载博客请征得博主同意Orz
  • 相关阅读:
    一个请求在Struts2框架中的处理流程
    最大公约数和最小公倍数--java实现
    项目技术总结
    项目学习经验
    MyEclipse Project Migration功能中文简单介绍
    RSA的傻瓜原理
    Class.forName()的作用
    matplotlib 画封闭图像并填充
    matplotlib 做图通过弹出窗口展示 spyder
    pyodbc 一些内容
  • 原文地址:https://www.cnblogs.com/sdfzhsz/p/9325765.html
Copyright © 2011-2022 走看看