hdu 3061 Battle 最大权闭合图

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3061

由于小白同学近期习武十分刻苦,很快被晋升为天策军的统帅。而他上任的第一天,就面对了一场极其困难的战斗:
据侦查兵回报,前方共有N座城池,考虑到地势原因,最终得到一个结论:攻占某些城池之前必须攻占另外一些城池。
事实上,可以把地图看做是一张拓扑图,而攻占某个城池,就意味着必须先攻占它的所有前驱结点。
小白还做了一份调查,得到了攻占每个城池会对他的兵力产生多少消耗(当然也可能会得到增长,因为每攻占一个城池,便可以整顿军队,扩充兵力,天策军的兵力十分庞大,如果不考虑收益,他们可以攻取所有的城池)。
现在请你帮小白统帅做一份战斗计划,挑选攻打哪些城市,使得天策军在战斗过后军容最为壮大。
 
题意描述:如题所示。
算法分析:最大权闭合图的水题。
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<cstdlib>
  5 #include<cmath>
  6 #include<algorithm>
  7 #include<queue>
  8 #define inf 0x7fffffff
  9 using namespace std;
 10 const int maxn=500+10;
 11 const int M = 250000+10;
 12 
 13 int n,m,from,to;
 14 struct node
 15 {
 16     int v,flow;
 17     int next;
 18 }edge[M*3];
 19 int head[maxn],edgenum;
 20 
 21 void add(int u,int v,int flow)
 22 {
 23     edge[edgenum].v=v ;edge[edgenum].flow=flow ;
 24     edge[edgenum].next=head[u] ;head[u]=edgenum++ ;
 25 
 26     edge[edgenum].v=u ;edge[edgenum].flow=0 ;
 27     edge[edgenum].next=head[v] ;head[v]=edgenum++ ;
 28 }
 29 
 30 int d[maxn];
 31 int bfs()
 32 {
 33     memset(d,0,sizeof(d));
 34     d[from]=1;
 35     queue<int> Q;
 36     Q.push(from);
 37     while (!Q.empty())
 38     {
 39         int u=Q.front() ;Q.pop() ;
 40         for (int i=head[u] ;i!=-1 ;i=edge[i].next)
 41         {
 42             int v=edge[i].v;
 43             if (!d[v] && edge[i].flow)
 44             {
 45                 d[v]=d[u]+1;
 46                 Q.push(v);
 47                 if (v==to) return 1;
 48             }
 49         }
 50     }
 51     return 0;
 52 }
 53 
 54 int dfs(int u,int flow)
 55 {
 56     if (u==to || flow==0) return flow;
 57     int cap=flow;
 58     for (int i=head[u] ;i!=-1 ;i=edge[i].next)
 59     {
 60         int v=edge[i].v;
 61         if (d[v]==d[u]+1 && edge[i].flow)
 62         {
 63             int x=dfs(v,min(edge[i].flow,cap));
 64             edge[i].flow -= x;
 65             edge[i^1].flow += x;
 66             cap -= x;
 67             if (cap==0) return flow;
 68         }
 69     }
 70     return flow-cap;
 71 }
 72 
 73 int dinic()
 74 {
 75     int sum=0;
 76     while (bfs()) sum += dfs(from,inf);
 77     return sum;
 78 }
 79 
 80 int main()
 81 {
 82     while (scanf("%d%d",&n,&m)!=EOF)
 83     {
 84         int a,b;
 85         memset(head,-1,sizeof(head));
 86         edgenum=0;
 87         from=n+1;
 88         to=from+1;
 89         int sum=0;
 90         for (int i=1 ;i<=n ;i++)
 91         {
 92             scanf("%d",&a);
 93             if (a>0) {sum += a ;add(from,i,a);}
 94             else add(i,to,-a);
 95         }
 96         for (int i=0 ;i<m ;i++)
 97         {
 98             scanf("%d%d",&a,&b);
 99             add(a,b,inf);
100         }
101         printf("%d\n",sum-dinic());
102     }
103     return 0;
104 }

 

posted @ 2015-03-22 21:12  huangxf  阅读(439)  评论(0编辑  收藏  举报