hdu 3996 Gold Mine ( 最大权闭合图 )

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

题意 :  

  1. 题意: 有 n 个金矿,每个金矿开发需要一定的价值,开发之后可以获得一定的价值,而且一些金矿受到另一些金矿的限制,即开采这个金矿之前要开采 
  2.            限制它的金矿,问最多可以获得多少价值。

题解:

      很明显的 最大权闭合图    金矿 ,有  开采的 花费 和价值 ,那么  开采的 利益就 是   价值 - 花费  ;

    

  1. 如果某个金矿的开发利润为正值,就在源点和该点之间连一条容量为该利润的边 
  2.           如果某个金矿的开发利润为负值,就在该点和汇点之间连一条容量为该利润绝对值的边 
  3.           如果某个金矿收到另一个金矿的限制,就在两个金矿之间连一条容量为INF的边。 
  4.           累计所有正值利润的和  sum,获得的最大利润为sum - maxflow


  1  #include<stdio.h>
  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 Min(a,b) a<b?a:b
 12   #define Max(a,b) a>b?a:b
 13   #define CL(a,num) memset(a,num,sizeof(a));
 14   #define maxn  5100
 15   #define eps  1e-6
 16   #define inf  10000000000
 17   #define read() freopen("data.in","r",stdin) ;
 18   #define ll __int64
 19   using  namespace std;
 20  ll n , m ;
 21   struct node
 22  {
 23       int  from;
 24       int to ;
 25      ll flow ;
 26       int next ;
 27  } p[maxn* 100];
 28   int  head[maxn] ,s,t,cnt,dis[maxn];
 29  ll a[maxn]  ,ans,num,sum;
 30 
 31   bool vis[maxn] ;
 32 
 33  queue< int>que ;
 34   void add( int  from , int to , ll flow )
 35  {
 36      p[cnt].to = to ;
 37      p[cnt].flow =flow ;
 38      p[cnt].next = head[ from] ;
 39      head[ from] = cnt++ ;
 40 
 41      p[cnt].to =  from ;
 42      p[cnt].flow =  0 ;
 43      p[cnt].next  = head[to] ;
 44      head[to] = cnt++ ;
 45 
 46  }
 47 
 48   int bfs()
 49  {
 50      CL(dis,- 1)  ;
 51      dis[s] =   0 ;
 52       int i ;
 53       while(!que.empty())que.pop() ;
 54 
 55      que.push(s) ;
 56       while(!que.empty())
 57      {
 58           int u = que.front() ;que.pop() ;
 59 
 60           for(i = head[u] ; i != - 1  ;i = p[i].next)
 61          {
 62                  int v = p[i].to ;
 63 
 64                 ll flow  = p[i].flow ;
 65 
 66                  if(flow >  0)
 67                  if(dis[v] <  0 )
 68                 {
 69                     dis[v] = dis[u] +  1 ;
 70                     que.push(v) ;
 71                 }
 72 
 73          }
 74 
 75      }
 76 
 77       if(dis[t] >  0return  1;
 78       else  return  0 ;
 79 
 80 
 81 
 82  }
 83 
 84 
 85  ll dfs( int x,ll mx)
 86  {
 87 
 88 
 89       if(x == t)  return mx ;
 90 
 91       int i ;
 92      ll a ,tf =  0;
 93 
 94 
 95        for(i = head[x] ; i != - 1 ; i = p[i].next)
 96       {
 97            int v = p[i].to ;
 98           ll  flow  = p[i].flow ;
 99            if(flow >  0)
100           {
101                 if( dis[v] == dis[x] +  1 && (a = dfs(v,min(flow ,mx))))
102             {
103                p[i].flow -= a ;
104                p[i^ 1].flow += a;
105 
106               return a ;
107             }
108 
109           }
110 
111       }
112 
113 
114        if(!tf) dis[x] = -  1;
115        return tf ;
116 
117  }
118 
119  ll dinic()
120  {
121 
122      ans =  0 ;
123      ll res =  0 ;
124       while(bfs())
125      {
126           while(res = dfs(s,inf))ans += res ;
127      }
128 
129       return  ans  ;
130 
131 
132  }
133 
134  int main()
135 {
136      int T,i,j,a,b,num ;
137     ll cost ,val;
138     scanf( " %d ",&T);
139      int cas =  0 ;
140     ll  sum ;
141      while(T--)
142     {
143 
144         CL(head, - 1) ;
145         cnt =  0 ;
146         sum =  0 ;
147         scanf( " %d ",&n);
148 
149         s =  0 ;
150         t = n* 26 + n +  1 ;
151 
152          for(i =  1 ; i <= n;i++)
153         {
154             scanf( " %d ",&m);
155              for(j =  1 ;  j <= m;j++)
156             {
157                 scanf( " %I64d%I64d%d ",&cost,&val,&num);
158 
159                 ll  tmp = val -  cost ;
160                  if(tmp >  0)
161                 {
162                     add(s,i* 26 + j,tmp);
163 
164                      sum += tmp ;
165                 }
166                  else
167                 {
168                      add(i* 26 + j,t, -tmp) ;
169 
170                 }
171 
172 
173                  while(num--)
174                 {
175                     scanf( " %d%d ",&a,&b);
176                     add(i* 26+j,a* 26 + b,inf) ;
177                 }
178             }
179         }
180 
181         ll ans = dinic() ;
182 
183         printf( " Case #%d: %I64d\n ",++cas,sum - ans) ;
184 
185     }
186 }

 


 


转载于:https://www.cnblogs.com/acSzz/archive/2012/11/10/2763896.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值