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;
}
时间: 2024-11-02 16:31:47

AOJ 2230 How to Create a Good Game(费用流)的相关文章

AOJ 2266 Cache Strategy(费用流)

[题目链接] http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2266 [题目大意] 有M个桶,N个球,球编号为1到N,每个球都有重量w_i. 给出一个长K的数列,数列由球的编号构成.开始的时候,桶都是空的. 接着我们从前往后从数列中取出一个数a_j,执行如下操作: 如果球a_j已经存在于某一个桶中,那么什么也不干,花费为0,继续. 如果任何桶中都没有a_j,那么找一个桶放a_j, 如果该桶里还有球,那么取出原来的球,将a_j放进

Aizu Aoj 2266 (费用流

题目(原文是日语): Google Code Jam区域赛上,坐在右前方的男人ID叫lyrically.东京大学时代的记忆中,记得有个朋友也用类似的ID.不过我的朋友都是萌妹子,我记忆中的 lyrically不仅算法扎实,封装也很强,能一下子给出问题的正解.比如,对我们写得不好的程序也能优化到AC的程度.她说,程序优化时,对缓存池的 利用特别重要. 那么问题来了,现在请你优化下面的缓存池模型: 有M个桶,N个球,球编号为1到N,每个球都有重量w_i.然后给出一个长K的数列,数列由球的编号构成.开

可逆加密解密单元文件和调用方法

1 (**************************************************) 2 (* *) 3 (* Advanced Encryption Standard (AES) *) 4 (* Interface Unit v1.3 *) 5 (* *) 6 (* *) 7 (* Copyright (c) 2002 Jorlen Young *) 8 (* *) 9 (* *) 10 (* *) 11 (*说明: *) 12 (* *) 13 (* 基于 ElASE

nanomsg 如何写数据到PipelineDB

nanomsg:https://github.com/nanomsg/nanomsg PipelineDB:https://github.com/pipelinedb/pipelinedb nanomsgToPipelineDB:https://github.com/sangli00/nanomsgtopdb 创建extension pipeline=# create extension nanomsgtopdb ; CREATE EXTENSION 默认数据接收流 pipeline=# \d

题单二:图论500

http://wenku.baidu.com/link?url=gETLFsWcgddEDRZ334EJOS7qCTab94qw5cor8Es0LINVaGMSgc9nIV-utRIDh--2UwRLvsvJ5tXFjbdpzbjygEdpGehim1i5BfzYgYWxJmu ==========  以下是最小生成树+并查集=========================[HDU]1213         How Many Tables        基础并查集★1272         小

图论五百题!

生死看淡不服就淦,这才是人生! =============================以下是最小生成树+并查集======================================[HDU]1213 How Many Tables 基础并查集★1272 小希的迷宫 基础并查集★1325&&poj1308 Is It A Tree? 基础并查集★1856 More is better 基础并查集★1102 Constructing Roads 基础最小生成树★1232 畅通工程 基

图论 500题——主要为hdu/poj/zoj

转自——http://blog.csdn.net/qwe20060514/article/details/8112550 =============================以下是最小生成树+并查集======================================[HDU]1213   How Many Tables   基础并查集★1272   小希的迷宫   基础并查集★1325&&poj1308  Is It A Tree?   基础并查集★1856   More i

序列化和反序列化

两种方法: 1.using System.Runtime.Serialization.Formatters.Binary;//二进制序列化器所在命名空间2.using System.Runtime.Serialization.Formatters.Soap;//using System.IO;//流的 反序列化:流--->对象 一个类要想能够序列化,需要给这个类加一个attribute:即在类的定义之前加[Serializable],写在using xxxx  下面,命名空间之外. 二进制格式化

加密解密大汇总

在项目开发中,出于系统安全考虑,我们总会想到使用加密解密进行处理.首先保证的一点就是数据被窃取后,不能使其正常阅读.其次,就是防止接口随意调用. (PS:鄙人目前就想到了这两点好处,如果还有什么优点,欢迎给位补充o(^▽^)o) 接下来就说几个常用的加密算法:DES加密算法,AES加密算法,RSA加密算法,Base64加密算法,MD5加密算法,SHA1加密算法 1.DES加密算法 加密方式---- 使用异或,置换,代换,移位四种基本运算进行16轮循环加密而成. 共分为一般加密和三重加密>> D