码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 3996 Gold Mine(最小割---最大权闭合)

时间:2014-09-02 21:24:15      阅读:505      评论:0      收藏:0      [点我收藏+]

标签:acm   c语言   算法   编程   网络流   

题目地址:HDU 3996

很简单的最大权闭合题,只不过有个小小的坑点。。那就是需要用int64。。。。但是为什么我交上去返回的TLE。。。。

建图思路:分别对每一层的金矿都编号。方便处理。然后源点连接正权点,汇点连接负权点,每个点连接它所依赖的。

用正权之和减去最大流即为答案。

代码如下:

#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <stdlib.h>
#include <math.h>
#include <ctype.h>
#include <queue>
#include <map>
#include <set>
#include <algorithm>

using namespace std;
#define LL __int64
const LL INF=1e15;
int head[3000], cnt, source, sink, nv, ren[120];
LL val[3000];
int d[3000], num[3000], pre[3000], cur[3000];
struct node
{
    int u, v, next;
    LL cap;
} edge[1000000];
void add(int u, int v, LL cap)
{
    edge[cnt].v=v;
    edge[cnt].cap=cap;
    edge[cnt].next=head[u];
    head[u]=cnt++;

    edge[cnt].v=u;
    edge[cnt].cap=0;
    edge[cnt].next=head[v];
    head[v]=cnt++;
}
void bfs()
{
    memset(d,-1,sizeof(d));
    memset(num,0,sizeof(num));
    queue<int>q;
    q.push(sink);
    d[sink]=0;
    num[0]=1;
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        for(int i=head[u]; i!=-1; i=edge[i].next)
        {
            int v=edge[i].v;
            if(d[v]==-1)
            {
                d[v]=d[u]+1;
                num[d[v]]++;
                q.push(v);
            }
        }
    }
}
LL isap()
{
    memcpy(cur,head,sizeof(cur));
    int u=pre[source]=source, i;
    LL flow=0;
    bfs();
    while(d[source]<nv)
    {
        if(u==sink)
        {
            LL f=INF;
            int pos;
            for(i=source; i!=sink; i=edge[cur[i]].v)
            {
                if(f>edge[cur[i]].cap)
                {
                    f=edge[cur[i]].cap;
                    pos=i;
                }
            }
            for(i=source; i!=sink; i=edge[cur[i]].v)
            {
                edge[cur[i]].cap-=f;
                edge[cur[i]^1].cap+=f;
            }
            flow+=f;
            u=pos;
        }
        for(i=cur[u]; i!=-1; i=edge[i].next)
        {
            if(d[edge[i].v]+1==d[u]&&edge[i].cap)
            {
                break;
            }
        }
        if(i!=-1)
        {
            cur[u]=i;
            pre[edge[i].v]=u;
            u=edge[i].v;
        }
        else
        {
            if(--num[d[u]]==0) break;
            int mind=nv;
            for(i=head[u]; i!=-1; i=edge[i].next)
            {
                if(mind>d[edge[i].v]&&edge[i].cap)
                {
                    mind=d[edge[i].v];
                    cur[u]=i;
                }
            }
            d[u]=mind+1;
            num[d[u]]++;
            u=pre[u];
        }
    }
    return flow;
}
int main()
{
    int t, n, m, i, num=0, k, tot, j, c, d;
    LL a, b, sum;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        num++;
        memset(head,-1,sizeof(head));
        cnt=0;
        sum=tot=0;
        for(j=1; j<=n; j++)
        {
            scanf("%d",&m);
            ren[j]=tot;
            for(i=1; i<=m; i++)
            {
                scanf("%I64d%I64d%d",&a,&b,&k);
                val[++tot]=b-a;
                while(k--)
                {
                    scanf("%d%d",&c,&d);
                    add(tot,ren[c]+d,INF);
                }
            }
        }
        source=0;
        sink=tot+1;
        nv=sink+1;
        for(i=1; i<=tot; i++)
        {
            if(val[i]>0)
            {
                add(source,i,val[i]);
                sum+=val[i];
            }
            else
                add(i,sink,-val[i]);
        }
        printf("Case #%d: ",num);
        printf("%I64d\n",sum-isap());
    }
    return 0;
}


HDU 3996 Gold Mine(最小割---最大权闭合)

标签:acm   c语言   算法   编程   网络流   

原文地址:http://blog.csdn.net/scf0920/article/details/39011655

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!