1 2 1 10 100 0 2 10 100 1 1 1 10 100 1 1 1
Case #1: 270
题意:有一些金矿区域,挖一个金矿时必须挖掉上边的跟他关联的,为最多赚的钱数。输入解释:第一个行是样例的组数。第二行表示有n个区域,接下来的一行m表示第i个区域的金矿的个数为m。接下来的m行为这个区域金矿花费的钱数,获得钱数,以及相关连的金矿的个数w,(下面的w行就是表示这些相关联的金矿的区域和在这个区域的第几个)。
思路:最大闭合图。类似poj 2987.建图时把每层的金矿数固定,然后编号建边。
代码:
/* ***********************************************
Author :rabbit
Created Time :2014/3/8 22:19:12
File Name :treap2.cpp
************************************************ */
#pragma comment(linker, "/STACK:102400000,102400000")
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <string>
#include <time.h>
#include <math.h>
#include <queue>
#include <stack>
#include <set>
#include <map>
using namespace std;
#define INF 10000000000000LL
#define eps 1e-8
#define pi acos(-1.0)
typedef __int64 ll;
const ll maxn=3199;
const ll maxm=400010;
struct Edge{
ll to,next,cap,flow;
Edge(){};
Edge(ll _next,ll _to,ll _cap,ll _flow)`{
next=_next;to=_to;cap=_cap;flow=_flow;
}
}edge[maxm];
ll head[maxn],tol,gap[maxn],dep[maxn],cur[maxn];
void addedge(ll u,ll v,ll flow){
edge[tol]=Edge(head[u],v,flow,0);head[u]=tol++;
edge[tol]=Edge(head[v],u,0,0);head[v]=tol++;
}
ll Q[maxn];
void bfs(ll start,ll end){
memset(dep,-1,sizeof(dep));
memset(gap,0,sizeof(gap));
gap[0]++;ll front=0,rear=0;
dep[end]=0;Q[rear++]=end;
while(front!=rear){
ll u=Q[front++];
for(ll i=head[u];i!=-1;i=edge[i].next){
ll v=edge[i].to;if(dep[v]==-1&&edge[i].cap)
Q[rear++]=v,dep[v]=dep[u]+1,gap[dep[v]]++;
}
}
}
ll S[maxn];
ll sap(ll start,ll end,ll N){
bfs(start,end);
memcpy(cur,head,sizeof(head));
ll top=0,u=start,ans=0;
while(dep[start]<N){
if(u==end){
ll MIN=INF,id;
for(ll i=0;i<top;i++)
if(MIN>edge[S[i]].cap-edge[S[i]].flow)
MIN=edge[S[i]].cap-edge[S[i]].flow,id=i;
for(ll i=0;i<top;i++)
edge[S[i]].flow+=MIN,edge[S[i]^1].flow-=MIN;
ans+=MIN,top=id,u=edge[S[top]^1].to;
continue;
}
bool flag=0;ll v;
for(ll i=cur[u];i!=-1;i=edge[i].next){
v=edge[i].to;
if(edge[i].cap-edge[i].flow&&dep[v]+1==dep[u]){
flag=1;cur[u]=i;break;
}
}
if(flag){
S[top++]=cur[u];u=v;continue;
}
ll MIN=N;
for(ll i=head[u];i!=-1;i=edge[i].next)
if(edge[i].cap-edge[i].flow&&dep[edge[i].to]<MIN)
MIN=dep[edge[i].to],cur[u]=i;
if(--gap[dep[u]]==0)break;gap[dep[u]=MIN+1]++;
if(u!=start)u=edge[S[--top]^1].to;
}
return ans;
}
int main()
{
//freopen("data.in","r",stdin);
//freopen("data.out","w",stdout);
ll T,t;
scanf("%I64d",&T);
for(ll t=1;t<=T;t++){
memset(head,-1,sizeof(head));tol=0;
ll sum=0;
ll laynum;
scanf("%I64d",&laynum);
for(ll i=1;i<=laynum;i++){
ll jin;
scanf("%I64d",&jin);
for(ll j=1;j<=jin;j++){
ll a,b,c;
scanf("%I64d%I64d%I64d",&a,&b,&c);
b-=a;
if(b>0){
sum+=b;
addedge(0,i*26+j,b);
}
else addedge(i*26+j,3000,-b);
while(c--){
ll u,v;
scanf("%I64d%I64d",&u,&v);
addedge(i*26+j,u*26+v,INF);
}
}
}
ll cnt=sap(0,3000,10000);
printf("Case #%I64d: %I64d\n",t,sum-cnt);
}
return 0;
}
hdu 3996 最大权闭合子图,布布扣,bubuko.com
原文:http://blog.csdn.net/xianxingwuguan1/article/details/20802505