据侦查兵回报,前方共有N座城池,考虑到地势原因,最终得到一个结论:攻占某些城池之前必须攻占另外一些城池。
事实上,可以把地图看做是一张拓扑图,而攻占某个城池,就意味着必须先攻占它的所有前驱结点。
小白还做了一份调查,得到了攻占每个城池会对他的兵力产生多少消耗(当然也可能会得到增长,因为每攻占一个城池,便可以整顿军队,扩充兵力,天策军的兵力十分庞大,如果不考虑收益,他们可以攻取所有的城池)。
现在请你帮小白统帅做一份战斗计划,挑选攻打哪些城市,使得天策军在战斗过后军容最为壮大。
接着输入一个M,代表城池和城池之间的拓扑关系数。
接着输入N个数字 代表从1 到 N 编号城池的战斗消耗(负数代表将要消耗天策军兵力,正数表示天策军可以获得相应的战斗收益)
最后M行 每行2个数字 a,b,代表相应城池的编号。
表示攻占b之后才可以攻占a;
5 5 8 -8 -10 12 -10 1 2 2 5 1 4 3 4 4 5
2
//
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=2010;
const int M=550000;//500000 不够
const int inf=(1<<28);
int head[N];
struct Edge
{
int u,v,next,w;
} edge[M];
int cnt,n,s,t;//n从0开始 0->n-1
void addedge(int u,int v,int w)
{
edge[cnt].u=u;
edge[cnt].v=v;
edge[cnt].w=w;
edge[cnt].next=head[u];
head[u]=cnt++;
edge[cnt].u=v;
edge[cnt].v=u;
edge[cnt].w=0;
edge[cnt].next=head[v];
head[v]=cnt++;
}
int sap()
{
int pre[N],cur[N],dis[N],gap[N];
int flow=0,aug=inf,u;
bool flag;
for(int i=0; i<n; i++)
{
cur[i]=head[i];
gap[i]=dis[i]=0;
}
gap[s]=n;
u=pre[s]=s;
while(dis[s]<n)
{
flag=0;
for(int &j=cur[u]; j!=-1; j=edge[j].next)
{
int v=edge[j].v;
if(edge[j].w>0&&dis[u]==dis[v]+1)
{
flag=1;
if(edge[j].w<aug) aug=edge[j].w;
pre[v]=u;
u=v;
if(u==t)
{
flow+=aug;
while(u!=s)
{
u=pre[u];
edge[cur[u]].w-=aug;
edge[cur[u]^1].w+=aug;
}
aug=inf;
}
break;
}
}
if(flag) continue;
int mindis=n;
for(int j=head[u]; j!=-1; j=edge[j].next)
{
int v=edge[j].v;
if(edge[j].w>0&&dis[v]<mindis)
{
mindis=dis[v];
cur[u]=j;
}
}
if((--gap[dis[u]])==0)
break;
gap[dis[u]=mindis+1]++;
u=pre[u];
}
return flow;
}
//初始化 cnt=0;memset(head,-1,sizeof(head));
//最大权闭合图 = sigma(val)(val>0)-最小割
//建图:构造一个源点S,汇点T。我们将S与所有权值为正的点连一条容
//量为其权值的边,将所有权值为负的点与T连一条容量为其权值的绝对值
//的边,原来的边将其容量定为正无穷。
//最小割所产生的两个集合中,其源点S所在集合(除去S)为最大权闭合图。
int main()
{
int m,p;
while(scanf("%d%d",&m,&p)==2)
{
int sum=0;
n=m+2;
s=0,t=n-1;
cnt=0;
memset(head,-1,sizeof(head));
for(int i=1;i<=m;i++)
{
int val;scanf("%d",&val);
if(val>0)
{
addedge(s,i,val);
sum+=val;
}
else addedge(i,t,-val);
}
while(p--)
{
int a,b;//攻占b之后才可以攻占a;
scanf("%d%d",&a,&b);//a->b=inf
addedge(a,b,inf);
}
int mc=sap();
printf("%d\n",sum-mc);
}
return 0;
}