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 }

 

 

 

 

 

 

你可能感兴趣的:(HDU)