hdu 3879 Base Station (最大权 闭合图)

http://acm.hdu.edu.cn/showproblem.php?pid=3879

 

好纠结的一道题啊 ,竟然 卡网络流的算法  。。。。。。用  dinic  tle   。。。。改为  isap  过了。。。。。。。

题意:

 

有n<= 5000个点可以用来建Station,题目给出了m个xi yi ci表示建立xi和yi个站点公司将获利ci,修建每个站点还需要成本, 让你求如何修建站点能使公司的收益最大?

 

题解:

   找出依赖关系  要获得利益 ci  则  要 有建立  站 a  和 站 b  所以   添加一个  点  c   权值 为正   ,要修的 站 权值  为 负  连接  c->a  .c->b ;

  然后 求 最大权闭合图 即可!!

 

 

  1 #include<cstdio>
  2  #include<cstring>
  3  #include<cmath>
  4  #include<iostream>
  5  #include<algorithm>
  6  #include<set>
  7  #include<map>
  8  #include<queue>
  9  #include<vector>
 10  #include<string>
 11  #define inf 0x7fffffff
 12  #define maxn 60000
 13  #define CL(a,b) memset(a,b,sizeof(a))
 14 
 15  using namespace std;
 16  struct node
 17  {
 18      int to;
 19      int cap;
 20      int  next;
 21  }p[maxn*10] ;
 22  int dis[maxn],gap[maxn] ,cnt,next[maxn],s,e;// dis[i]为 到达 原点的层数
 23  int  n , m,NN ;//NN 为  加完点 之后的 总结点数
 24  void add(int from,int to,int cap)//加 的 是 有向边
 25  {
 26      p[cnt].to = to;
 27      p[cnt].cap = cap ;
 28      p[cnt].next = next[from];
 29      next[from] = cnt++;
 30 
 31      p[cnt].to = from;
 32      p[cnt].cap = 0;
 33      p[cnt].next = next[to];
 34      next[to] = cnt++ ;
 35  }
 36  int dfs(int pos,int cost)
 37  {
 38 
 39      if(pos == e)
 40       return cost ;
 41 
 42      int i,j ,mdis = NN ,f = cost ;
 43 
 44      for(i =  next[pos];i != - 1; i = p[i].next)
 45      {
 46          int to = p[i].to ;
 47          int cap = p[i].cap ;
 48          if(cap > 0 )
 49          {
 50              if(dis[to] + 1 == dis[pos])
 51              {
 52 
 53 
 54                int d = min(f,cap) ;// 注意 这 为 剩余 流量 和 cap 的 最小值
 55 
 56                d = dfs(to,d) ;
 57                p[i].cap -=d;
 58                p[i^1].cap +=d;
 59                f -= d;
 60 
 61                if(dis[s] >= NN)  return cost - f;// 如果没有 了 增广路经 结束算法
 62                if(f == 0break ;
 63              }
 64              if( dis[to] < mdis ) mdis = dis[to] ;// 记录可扩展的最小的狐
 65 
 66          }
 67 
 68      }
 69      if(f == cost)//  没有 可以 扩展的点
 70      {
 71          --gap[dis[pos]];
 72          if(gap[dis[pos]] == 0)dis[s] = NN;// 注意这 ,若 距离 为 dis[pos] 这一层都没有 扩展点了(断层) dis[s] = n
 73 
 74          dis[pos] = mdis + 1;//维护距离标号的方法是这样的:当找增广路过程中发现某点出发没有允许弧时,将这个点的距离标号设为由它出发的所有弧的终点的距离标号的最                                     小值加一
 75 
 76          ++gap[dis[pos]] ;
 77      }
 78      return cost  - f ;
 79  }
 80  int isap( int b,int t)
 81  {
 82 
 83      int ret =  0;
 84      s = b;
 85      e = t;
 86      CL(gap,0);
 87      CL(dis,0) ;
 88      gap[s] = NN ;//NN 为  加完点 之后的 总结点数
 89      while(dis[s] < NN)
 90      {
 91          ret+=dfs(s,inf) ;
 92      }
 93      return ret ;
 94 
 95  }
 96  int a[maxn] ;
 97 int main()
 98 {
 99     //read() ;
100     int i, x,y;
101     int d ;
102      while(scanf("%d%d",&n,&m)!=EOF)
103      {
104          int sum  = 0 ;
105 
106          CL(next, -1);
107 
108 
109          cnt = 0  ;
110          int b = 0 ;
111          int t = n + m + 1 ;
112          NN  = n + m + 2;
113          for(i = 1; i <= n;i++)
114          {
115              scanf("%d",&a[i]) ;
116              add(i,t,a[i]) ;
117          }
118 
119 
120          for(i = 1 ; i <= m;i++)
121          {
122              scanf("%d%d%d",&x,&y,&d);
123 
124              add(b,n+i,d) ;
125 
126              sum += d ;
127 
128              add(n + i,x,inf) ;
129 
130 
131              add(n + i ,y,inf) ;
132 
133 
134 
135 
136          }
137 
138          int ans  = isap(b,t) ;
139 
140 
141          //printf("%I64d   %I64d  +++++\n",sum , ans) ;
142          printf("%d\n",sum - ans) ;
143      }
144 }

 

 

 

 

 

 

posted @ 2012-11-10 17:03  Szz  阅读(403)  评论(0编辑  收藏  举报