HDU 3061 Battle 最大权闭合图

来源:互联网 发布:台北北投温泉攻略 知乎 编辑:程序博客网 时间:2024/04/25 08:58

Battle

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 863    Accepted Submission(s): 420


Problem Description
由于小白同学近期习武十分刻苦,很快被晋升为天策军的统帅。而他上任的第一天,就面对了一场极其困难的战斗:
据侦查兵回报,前方共有N座城池,考虑到地势原因,最终得到一个结论:攻占某些城池之前必须攻占另外一些城池。
事实上,可以把地图看做是一张拓扑图,而攻占某个城池,就意味着必须先攻占它的所有前驱结点。
小白还做了一份调查,得到了攻占每个城池会对他的兵力产生多少消耗(当然也可能会得到增长,因为每攻占一个城池,便可以整顿军队,扩充兵力,天策军的兵力十分庞大,如果不考虑收益,他们可以攻取所有的城池)。
现在请你帮小白统帅做一份战斗计划,挑选攻打哪些城市,使得天策军在战斗过后军容最为壮大。
 

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
 


不想再把模板写成结构体了。。。TLE。。。

正值和减去最小割

最大流最小割定理。。


#include <cstdlib>#include <cctype>#include <cstring>#include <cstdio>#include <cmath>#include <algorithm>#include <vector>#include <string>#include <iostream>#include <sstream>#include <map>#include <set>#include <queue>#include <stack>#include <fstream>#include <numeric>#include <iomanip>#include <bitset>#include <list>#include <stdexcept>#include <functional>#include <utility>#include <ctime>using namespace std;#define PB push_back#define MP make_pair#define CLR(vis) memset(vis,0,sizeof(vis))#define MST(vis,pos) memset(vis,pos,sizeof(vis))#define MAX3(a,b,c) max(a,max(b,c))#define MAX4(a,b,c,d) max(max(a,b),max(c,d))#define MIN3(a,b,c) min(a,min(b,c))#define MIN4(a,b,c,d) min(min(a,b),min(c,d))#define PI acos(-1.0)#define INF 0x7FFFFFFF#define LINF 1000000000000000000LL#define eps 1e-8typedef long long ll;typedef unsigned long long ull;const int mm=1111111;const int mn=1111;int node,s,t,edge,max_flow;int ver[mm],cap[mm],flow[mm],next[mm];int head[mn],work[mn],dis[mn],q[mn];inline void init(int _node,int _s,int _t){    node=_node, s=_s, t=_t;    for(int i=0;i<node;++i)        head[i]=-1;    edge=max_flow=0;}inline void addedge(int u,int v,int c){    ver[edge]=v,cap[edge]=c,flow[edge]=0,next[edge]=head[u],head[u]=edge++;    ver[edge]=u,cap[edge]=0,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++]=s ] = 0;    for(l=0;l<r;l++)    {       for(i=head[ u=q[l] ]; ~i ;i=next[i])        if(flow[i]<cap[i] && dis[ v=ver[i] ]<0)        {            dis[ q[r++]=v ]=dis[u]+1;            if(v==t) return 1;        }    }    return 0;}int Dinic_dfs(int u,int exp){    if(u==t) return exp;    for(int &i=work[u],v,temp; ~i ;i=next[i])    {        if(flow[i]<cap[i] && dis[ v=ver[i] ]==dis[u]+1 && ( temp=Dinic_dfs(v,min(exp,cap[i]-flow[i])) )>0)        {           flow[i]+=temp;           flow[i^1]-=temp;           return temp;        }    }    return 0;}int Dinic_flow(){    int res,i;    while(Dinic_bfs())    {        for(i=0;i<node;++i) work[i]=head[i];        while( ( res=Dinic_dfs(s,INF) ) )  max_flow+=res;    }    return  max_flow;}int main(){    int n,m;    while(scanf("%d%d",&n,&m)!=EOF)    {        int sum=0;        int tmp;        init(n+2,0,n+1);        for(int i=1;i<=n;i++)        {            scanf("%d",&tmp);            if(tmp>0)            {                sum+=tmp;                addedge(s,i,tmp);            }            if(tmp<0)            {                addedge(i,t,-tmp);            }        }        int u,v;        while(m--)        {            scanf("%d%d",&u,&v);            addedge(u,v,INF);        }        cout<<sum-Dinic_flow()<<endl;    }    return 0;}


0 0
原创粉丝点击