Gold Mine
Then for every case:
one line for layout number.(<=100)
for every layout
first line gold number(<=25)
then one line for the dig cost and the gold value(32bit integer), the related gold number that must be digged first(<=50)
then w lines descripte the related gold followed, each line two number, one layout num, one for the order in that layout
see sample for details
x for case number, count from 1.
y for the answer.
1 2 1 10 100 0 2 10 100 1 1 1 10 100 1 1 1
Case #1: 270
建图:
如果某个金矿的开发利润为正值,就在源点和该点之间连一条容量为该利润的边
如果某个金矿的开发利润为负值,就在该点和汇点之间连一条容量为该利润绝对值的边
如果某个金矿收到另一个金矿的限制,就在两个金矿之间连一条容量为INF的边。
累计所有正值利润的和 sum,获得的最大利润为sum - ans
#include<cstdio>
#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<cstdio>
#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;
}
4160



被折叠的 条评论
为什么被折叠?



