现在的位置: 首页 > 综合 > 正文

hdu 3996 (最大权闭合图)

2018年02月20日 ⁄ 综合 ⁄ 共 1567字 ⁄ 字号 评论关闭

题意:有n个区域布局,每个区域有一些金矿,挖开金矿需要一定的费用,可以得到一定的利润,要想挖开一个金矿,必须挖开所有在这个金矿上边的金矿,求最大利益,给的数据价值太大,用64位。

分析:如果一个金矿可以获利,就从源点引一条边,容量为获得的利益,否则向汇点引一条边,容量为损耗,一个金矿向所有的必须在它之前开发的金矿连边,容量为无穷大。求出最大流就是最小损耗,,,







#include<stdio.h>
#include<string.h>
const int N=2600;
const __int64 inf=0x3fffffffffffffff;
int dis[N],gap[N],head[N],num,start,end,ans;
struct edge
{
    int st,ed,next;
    __int64 flow;
}e[N*100];
void addedge(int x,int y,__int64 w)
{
    e[num].st=x;e[num].ed=y;e[num].flow=w;e[num].next=head[x];head[x]=num++;
    e[num].st=y;e[num].ed=x;e[num].flow=0;e[num].next=head[y];head[y]=num++;
}
__int64 dfs(int u,__int64 minflow)
{
    if(u==end)return minflow;
    int i,v,min_dis=ans-1;
    __int64 f,flow=0;
    for(i=head[u];i!=-1;i=e[i].next)
    {
        if(e[i].flow<=0)continue;
        v=e[i].ed;
        if(dis[v]+1==dis[u])
        {
            f=dfs(v,e[i].flow>minflow-flow?minflow-flow:e[i].flow);
            e[i].flow-=f;
            e[i^1].flow+=f;
            flow+=f;
            if(flow==minflow)break;
            if(dis[start]>=ans)return flow;
        }
        min_dis=min_dis>dis[v]?dis[v]:min_dis;
    }
    if(flow==0)
    {
        if(--gap[dis[u]]==0)
            dis[start]=ans;
        dis[u]=min_dis+1;
        gap[dis[u]]++;
    }
    return flow;
}
__int64 isap()
{
    __int64 maxflow=0;
    memset(dis,0,sizeof(head));
    memset(gap,0,sizeof(gap));
    gap[0]=ans;
    while(dis[start]<ans)
        maxflow+=dfs(start,inf);
    return maxflow;
}
int main()
{
    int i,j,n,m,t,x,y,w,op=1;
    __int64 sum;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        memset(head,-1,sizeof(head));
        num=0;start=0;end=n*25+1;sum=0;ans=end+1;
        for(i=0;i<n;i++)
        {
            scanf("%d",&m);
            for(j=1;j<=m;j++)
            {
                scanf("%d%d%d",&x,&y,&w);
                if(y-x>=0)
                {
                    addedge(start,i*25+j,y-x);
                    sum+=y-x;
                }
                else addedge(i*25+j,end,x-y);
                while(w--)
                {
                    scanf("%d%d",&x,&y);
                    addedge(i*25+j,(x-1)*25+y,inf);
                }
            }
        }
        printf("Case #%d: %I64d\n",op++,sum-isap());
    }
    return 0;
}






抱歉!评论已关闭.