zoukankan      html  css  js  c++  java
  • AOJ 2230 How to Create a Good Game(费用流)

    【题目链接】 http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2230

    【题目大意】

      给出一张图,从1到n的最长路不变的情况下,
      还能在不同的点之间增加最长总和的路为多长。

    【题解】

      From http://www.hankcs.com/program/algorithm/aoj-2230-how-to-create-a-good-game.html  

      如果将原DAG权值取反,然后从最后一关连一条正权边到第一关,
      权值是最短路(负权值最短路=传统意义上的最长路)的长度的话,
      那么那些正圈中的负权边就是应该增加权值的边,具体应该加多少,就是正圈的权值。
      新建源点汇点,对于所有顶点,如果入度>出度,从源点连一条边到它,
      否则,从它连一条边到汇点,容量都是是度数差。

    【代码】

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <vector>
    using namespace std;
    const int INF=0x3f3f3f3f;
    struct edge{
        int to,cap,cost,rev;
        edge(int to,int cap,int cost,int rev):to(to),cap(cap),cost(cost),rev(rev){}
    };
    const int MAX_V=10010;
    int V,dist[MAX_V],prevv[MAX_V],preve[MAX_V];
    vector<edge> G[MAX_V];
    void add_edge(int from,int to,int cap,int cost){
        G[from].push_back(edge(to,cap,cost,G[to].size()));
        G[to].push_back(edge(from,0,-cost,G[from].size()-1));
    }
    int min_cost_flow(int s,int t,int f){
        int res=0;
        while(f>0){
            fill(dist,dist+V,INF);
            dist[s]=0;
            bool update=1;
            while(update){
                update=0;
                for(int v=0;v<V;v++){
                    if(dist[v]==INF)continue;
                    for(int i=0;i<G[v].size();i++){
                        edge &e=G[v][i];
                        if(e.cap>0&&dist[e.to]>dist[v]+e.cost){
                            dist[e.to]=dist[v]+e.cost;
                            prevv[e.to]=v;
                            preve[e.to]=i;
                            update=1;
                        }
                    }
                }
            }
            if(dist[t]==INF)return -1;
            int d=f;
            for(int v=t;v!=s;v=prevv[v]){
                d=min(d,G[prevv[v]][preve[v]].cap);
            }f-=d;
            res+=d*dist[t];
            for(int v=t;v!=s;v=prevv[v]){
                edge &e=G[prevv[v]][preve[v]];
                e.cap-=d;
                G[v][e.rev].cap+=d; 
            }
        }return res;
    }
    void clear(){for(int i=0;i<V;i++)G[i].clear();}
    const int MAX_N=120; 
    int N,M;
    int in[MAX_N],out[MAX_N],tot;
    void solve(){
        int s=N,t=N+1;V=t+1;tot=0;
        clear();
        memset(in,0,sizeof(in));
        memset(out,0,sizeof(out));
        for(int i=0;i<M;i++){
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            add_edge(x,y,INF,-z);
            out[x]++;in[y]++;
            tot+=z;
        }int max_f=0;
        for(int i=0;i<N;i++){
            if(in[i]>out[i]){
                add_edge(s,i,in[i]-out[i],0);
                max_f+=in[i]-out[i];
            }else{
                add_edge(i,t,out[i]-in[i],0);
            }
        }min_cost_flow(0,N-1,1);
        add_edge(N-1,0,INF,-dist[N-1]);
        printf("%d
    ",min_cost_flow(s,t,max_f)-tot);
    }
    int main(){
         while(~scanf("%d%d",&N,&M)){
             solve();
         }return 0;
    }
  • 相关阅读:
    使用shell从DB2数据库导出数据
    kettle插入/更新
    kettle删除资源库中的转换或者作业
    DB2中的转义字符
    Kettle行列转换
    Linux查看文件以及文件夹的大小
    Linux下如何查看JDK安装路径
    使用Linux调用资源库中的Job报错-ERROR: No repository provided, can't load job.
    通过shell脚本获取日期,并赋给变量
    批处理判断是否存在文件,存在则运行另外一个bat文件
  • 原文地址:https://www.cnblogs.com/forever97/p/aoj2230.html
Copyright © 2011-2022 走看看