hdu 3879 Base Station (最大權 閉合圖)

weixin_30788239發表於2020-04-05

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 }

 

 

 

 

 

 

轉載於:https://www.cnblogs.com/acSzz/archive/2012/11/10/2764194.html

相關文章