建图:
如果某个金矿的开发利润为正值,就在源点和该点之间连一条容量为该利润的边
如果某个金矿的开发利润为负值,就在该点和汇点之间连一条容量为该利润绝对值的边
如果某个金矿收到另一个金矿的限制,就在两个金矿之间连一条容量为INF的边。
累计所有正值利润的和 sum,获得的最大利润为sum - ans
#include<cstring>
#define ll __int64
const int N=2505;
const int M=72600;
const ll INF=10000000000;
int tol,n,s,t;
ll ans;
int head[N],d[N];
struct node
{
ll f;
int y,nxt;
}edge[M];
ll min(ll a,ll b){return a<b?a:b;}
void add(int x,int y,ll f)
{
edge[tol].y=y;
edge[tol].f=f;
edge[tol].nxt=head[x];
head[x]=tol++;
edge[tol].y=x;
edge[tol].f=0;
edge[tol].nxt=head[y];
head[y]=tol++;
}
bool bfs()
{
int front=0,rear=0,q[N],u,v,i;
memset(d,-1,sizeof(d));
d[s]=0;
q[rear++]=s;
while(front<rear)
{
u=q[front++];
for(i=head[u];i!=-1;i=edge[i].nxt)
{
v=edge[i].y;
if(edge[i].f&&d[v]==-1)
{
d[v]=d[u]+1;
if(v==t)return 1;
q[rear++]=v;
}
}
}
return 0;
}
ll dfs(int s,ll limit)
{
if(s==t)return limit;
int i,v;
ll sum=0,tmp;
for(i=head[s];i!=-1;i=edge[i].nxt)
{
v=edge[i].y;
if(edge[i].f&&d[s]+1==d[v])
{
tmp=dfs(v,min(limit-sum,edge[i].f));
edge[i].f-=tmp;
edge[i^1].f+=tmp;
sum+=tmp;
if(limit==sum)return sum;
}
}
if(sum==0)d[s]=-1;
return sum;
}
void dinic(){while(bfs())ans+=dfs(s,INF);}
int main()
{
int T,ca=1,i,j,a,b,m,w,val,cost;
ll sum;
scanf("%d",&T);
while(T--)
{
memset(head,-1,sizeof(head));
scanf("%d",&n);
s=0,t=n*25+1;tol=0,ans=0;sum=0;
for(i=0;i<n;i++)
{
scanf("%d",&m);
for(j=1;j<=m;j++)
{
scanf("%d%d%d",&cost,&val,&w);
val-=cost;
if(val>0){add(s,i*25+j,val);sum+=val;}
else add(i*25+j,t,-val);
while(w--)
{
scanf("%d%d",&a,&b);
add(i*25+j,(a-1)*25+b,INF);
}
}
}
dinic();
printf("Case #%d: %I64d\n",ca++,sum-ans);
}
return 0;
}
#include<cstring>
#define ll __int64
const int N=2505;
const int M=72600;
const ll INF=10000000000;
int n,s,t,tol;
ll ans;
int head[N],arc[N],pre[N],dis[N],gap[N];
struct node
{
ll f;
int y,nxt;
}edge[M];
void add(int x,int y,ll f)
{
edge[tol].y=y;
edge[tol].f=f;
edge[tol].nxt=head[x];
head[x]=tol++;
edge[tol].y=x;
edge[tol].f=0;
edge[tol].nxt=head[y];
head[y]=tol++;
}
void sap()
{
memset(dis,0,sizeof(dis));
memset(gap,0,sizeof(gap));
memcpy(arc,head,sizeof(head));
gap[0]=n;
ll arg=INF;
int u=pre[s]=s;
while(dis[s]<n)
{
L:
for(int& i=arc[u];i!=-1;i=edge[i].nxt)
{
int v=edge[i].y;
if(edge[i].f&&dis[u]==dis[v]+1)
{
if(arg>edge[i].f)arg=edge[i].f;
pre[v]=u;u=v;
if(v==t)
{
ans+=arg;
for(u=pre[u];v!=s;v=u,u=pre[u])
{
edge[arc[u]].f-=arg;
edge[arc[u]^1].f+=arg;
}
arg=INF;
}
goto L;
}
}
int min=n;
for(int j=head[u];j!=-1;j=edge[j].nxt)
{
int v=edge[j].y;
if(edge[j].f&&min>dis[v])
{
arc[u]=j;
min=dis[v];
}
}
if(--gap[dis[u]]==0)break;
dis[u]=min+1;
gap[dis[u]]++;
u=pre[u];
}
}
int main()
{
int T,ca=1,i,j,a,b,m,w,cost,val;
ll sum;
scanf("%d",&T);
while(T--)
{
memset(head,-1,sizeof(head));
scanf("%d",&n);
s=0,t=n*25+1;tol=0,ans=0;sum=0;
for(i=0;i<n;i++)
{
scanf("%d",&m);
for(j=1;j<=m;j++)
{
scanf("%d%d%d",&cost,&val,&w);
val-=cost;
if(val>0){add(s,i*25+j,val);sum+=val;}
else add(i*25+j,t,-val);
while(w--)
{
scanf("%d%d",&a,&b);
add(i*25+j,(a-1)*25+b,INF);
}
}
}
n=t+1;
sap();
printf("Case #%d: %I64d\n",ca++,sum-ans);
}
return 0;
}
#include <cstdio>
#include <string.h>
using namespace std;
typedef long long ll;
const int N=3550;
const int M=9000000;
const ll inf=13216546513113211ll;
int head[N];
struct Edge{
int v,next;
ll w;
} edge[M];
int cnt,s=0;
void addedge(int u,int v,ll w)//这里存的还是一条有向边
{
edge[cnt].v=v;
edge[cnt].w=w;
edge[cnt].next=head[u];
head[u]=cnt++;
edge[cnt].v=u;
edge[cnt].w=0;
edge[cnt].next=head[v];
head[v]=cnt++;
}
ll sap(int t){
int pre[N],cur[N],dis[N],gap[N];
ll flow=0,aug=inf,u;
bool flag;
for(int i=0; i<=t; i++){
cur[i]=head[i];
gap[i]=dis[i]=0;
}
gap[s]=t+1;
u=pre[s]=s;
while(dis[s]<=t){
flag=0;
for(int &j=cur[u]; ~j; j=edge[j].next){
int v=edge[j].v;
if(edge[j].w>0&&dis[u]==dis[v]+1){
flag=1;
if(edge[j].w<aug) aug=edge[j].w;
pre[v]=u;
u=v;
if(u==t){
flow+=aug;
//printf("%d\n",flow);
while(u!=s){
u=pre[u];
edge[cur[u]].w-=aug;
edge[cur[u]^1].w+=aug;//异或是找与其配对的边
}
aug=inf;
}
break;
}
}
if(flag) continue;
int mindis=t+1;
for(int j=head[u]; ~j; j=edge[j].next){
int v=edge[j].v;
if(edge[j].w>0&&dis[v]<mindis){
mindis=dis[v];
cur[u]=j;
}
}
if((--gap[dis[u]])==0)
break;
gap[dis[u]=mindis+1]++;
u=pre[u];
}
return flow;
}
ll value[N];
void init()
{
memset (head , -1 , sizeof(head));
cnt=0;
}
int main ()
{
int cas;
int n,lay,c;
ll a,b;
ll sum=0;
int u,v;
scanf("%d",&cas);
for (int I=1 ; I<=cas ; ++I)
{
init();
sum=0;
scanf("%d",&lay);
for (int i=0 ; i<lay ; ++i)
{
scanf("%d",&n);
for (int j=0 ; j<n ; ++j)
{
scanf("%I64d%I64d%d",&a,&b,&c);
value[i*25+j+1]=b-a;
for (int k=0 ; k<c ; ++k)
{
scanf("%d%d",&u,&v);
u--;v--;
addedge(i*25+j+1,u*25+v+1,inf);
}
if(value[i*25+j+1]>0)
addedge(0,i*25+j+1,value[i*25+j+1]),sum+=value[i*25+j+1];
if(value[i*25+j+1]<0)
addedge(i*25+j+1,2550,-value[i*25+j+1]);
}
}
ll ans=sum-sap(2550);
//printf("%d\n",sum);
printf("Case #%d: %I64d\n",I,ans);
}
return 0;
}