HDu 3061 Battle(最大ストリーム最小分割の応用)

3619 ワード

Battle
Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 398    Accepted Submission(s): 186
Problem Description
白さんは最近、武術の練習に苦労したため、すぐに天策軍の統帥に昇進した.彼が就任した初日、極めて困難な戦いに直面した.
偵察兵の報いによると、前方にはN基の城があり、地勢の原因を考慮して、最終的にいくつかの城を攻略する前に他の城を攻略しなければならないという結論を得た.
実際、地図をトポロジーマップと見なすことができ、ある城を攻略することは、そのすべての前駆ノードを先に攻略しなければならないことを意味します.
シロはまた、各城を攻略すると兵力がどれだけ消費されるかを調査した(もちろん成長する可能性もある.1つの城を攻略するたびに、軍隊を整備し、兵力を拡充することができるため、天策軍の兵力は非常に膨大で、収益を考慮しなければ、彼らはすべての城を攻略することができる).
今、白統帥に戦闘計画を作ってもらい、どの都市を攻撃するかを選んで、天策軍が戦闘後、軍容が最も大きくなったようにしてください.
 
Input
まずNを入力するとN個の城がある(1<=n<=500)
次に、城と城の間のトポロジー関係数を表すMを入力します.
次にN個の数字を入力して1からN番城までの戦闘消費を表す(負数は天策軍兵力を消費し、正数は天策軍が相応の戦闘収益を得ることができることを示す)
最後にM行の各行の2つの数字a,bは、対応する城の番号を表す.
bを攻略してからaを攻略できることを表す.
 
Output
天策軍は最大でどれだけの戦闘収益を得ることができます
 
Sample Input

   
   
   
   
5 5 8 -8 -10 12 -10 1 2 2 5 1 4 3 4 4 5

 
Sample Output

   
   
   
   
2

 
Source
2009 Multi-University Training Contest 16 - Host by NIT
 
Recommend
lcy
 
タイトル:http://acm.hdu.edu.cn/showproblem.php?pid=3061
PS:この問題は意外にも急に図を考え出せなかったので、最小割の応用は熟練していないようですね~~~
分析:この問題は最小の割合を求めて、源と為替を増加することができて、源と重みが正の点を正の点につなげて上界をその点の重み値の辺につなげて、重みが負の点と合流上界がこの点の重み値の反対数の辺になって、それからaを攻略して先にbを占めなければならないならないならば、重み値の無限の辺a->bをつなげて、すべての正の値の和から最大の流れを減らして、つまり答えです.
コード:
#include<cstdio>
using namespace std;
const int mm=1111111;
const int mn=1111;
const int oo=1000000000;
int node,src,dest,edge;
int ver[mm],flow[mm],next[mm];
int head[mn],work[mn],dis[mn],q[mn];
inline int min(int a,int b)
{
    return a<b?a:b;
}
inline void prepare(int _node,int _src,int _dest)
{
    node=_node,src=_src,dest=_dest;
    for(int i=0;i<node;++i)head[i]=-1;
    edge=0;
}
inline void addedge(int u,int v,int c)
{
    ver[edge]=v,flow[edge]=c,next[edge]=head[u],head[u]=edge++;
    ver[edge]=u,flow[edge]=0,next[edge]=head[v],head[v]=edge++;
}
bool Dinic_bfs()
{
    int i,u,v,l,r=0;
    for(i=0;i<node;++i)dis[i]=-1;
    dis[q[r++]=src]=0;
    for(l=0;l<r;++l)
        for(i=head[u=q[l]];i>=0;i=next[i])
            if(flow[i]&&dis[v=ver[i]]<0)
            {
                dis[q[r++]=v]=dis[u]+1;
                if(v==dest)return 1;
            }
    return 0;
}
int Dinic_dfs(int u,int exp)
{
    if(u==dest)return exp;
    for(int &i=work[u],v,tmp;i>=0;i=next[i])
        if(flow[i]&&dis[v=ver[i]]==dis[u]+1&&(tmp=Dinic_dfs(v,min(exp,flow[i])))>0)
        {
            flow[i]-=tmp;
            flow[i^1]+=tmp;
            return tmp;
        }
    return 0;
}
int Dinic_flow()
{
    int i,ret=0,delta;
    while(Dinic_bfs())
    {
        for(i=0;i<node;++i)work[i]=head[i];
        while(delta=Dinic_dfs(src,oo))ret+=delta;
    }
    return ret;
}
int main()
{
    int u,v,c,m,n,sum;
    while(scanf("%d%d",&n,&m)!=-1)
    {
        prepare(n+2,0,n+1);
        for(u=1,sum=0;u<=n;++u)
        {
            scanf("%d",&c);
            if(c>0)addedge(src,u,c),sum+=c;
            if(c<0)addedge(u,dest,-c);
        }
        while(m--)scanf("%d%d",&u,&v),addedge(u,v,oo);
        printf("%d
",sum-Dinic_flow()); } return 0; }