AOJ 2230 How to Create a Good Game(费用流)

Posted forever97‘s blog

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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\n",min_cost_flow(s,t,max_f)-tot);
}
int main(){
     while(~scanf("%d%d",&N,&M)){
         solve();
     }return 0;
}

以上是关于AOJ 2230 How to Create a Good Game(费用流)的主要内容,如果未能解决你的问题,请参考以下文章

How difficult is it to create a JavaScript framework?

[转]How to: Create a Custom Principal Identity

How to create vlan on Linux (with Cisco Catalyst Switch)

How to create a repository in Github with Eclipse?

How to Create a Basic Plugin 如何写一个基础的jQuery插件

How to create a OnCellDblClick for Delphi's TDBGrid