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

hdu3996Gold Mine 最小割

时间:2015-08-17 15:42:11      阅读:139      评论:0      收藏:0      [点我收藏+]

标签:

//给出每个点的权值,
//从中选出一些点,使得这些点的权值和最大
//其中选择该点一定要选择在它前面的点,问最终的最大权值是多少
//对于所有正权的点与源点相连,权值为该点权值
//所有负权点与汇点相连,权值为该点权值的绝对值
//每一点与其前面的点相连,权值为无穷大
//这样求出这个图的最小割,用所有正权之和减去这个最小割即为结果
//减去最小割后剩下的点所有正权点集到负权的点集没有边相连,
//将所有正权点之和减去最小割即为减去不选的正权点和选了的负权点
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std ;
const int maxn = 2510 ;
const int maxm = 15e4+10 ;
typedef long long ll ;
const ll  inf = 1e15 ;
int st = 0 , en = 2501 ;
int nedge ;
int dis[maxn] , head[maxn] ;
struct Edge
{
    int v ;
    ll w;
    int next ;
}edge[maxm<<1] ;
void addedge(int u , int v , ll w)
{
    edge[nedge].v = v ;
    edge[nedge].w = w ;
    edge[nedge].next = head[u] ;
    head[u] = nedge++ ;
    edge[nedge].v = u ;
    edge[nedge].w = 0 ;
    edge[nedge].next = head[v] ;
    head[v] = nedge++ ;
}
bool bfs()
{
    memset(dis , -1 , sizeof(dis)) ;
    dis[st] = 0 ;
    queue<int> que ;
    que.push(st) ;
    while(que.size())
    {
        int u = que.front() ; que.pop() ;
        for(int i = head[u] ;i != -1 ;i = edge[i].next)
        {
            int v = edge[i].v ;
            if(dis[v] < 0 && edge[i].w)
            {
                dis[v] = dis[u] + 1 ;
                que.push(v) ;
            }
        }
    }
    if(dis[en] > 0)return true ;
    return false ;
}
ll dfs(int u , ll mx)
{
    if(u == en)
    return mx ;
    ll ans = 0 , a ;
    for(int i = head[u];i != -1 ;i = edge[i].next)
    {
        int v = edge[i].v ;
        if(dis[v] == dis[u] + 1 && edge[i].w && (a = dfs(v , min(mx , edge[i].w))))
        {
            mx -= a ;
            ans += a ;
            edge[i].w -= a ;
            edge[i^1].w += a ;
            if(!mx)break ;
        }
    }
    if(!ans)dis[u] = -1 ;
    return ans ;
}
int main()
{
    //freopen("in.txt" , "r" , stdin) ;
    int t ;int cas = 0 ;
    scanf("%d" , &t) ;
    while(t--)
    {
        int n , m ;
        scanf("%d" , &n) ;
        ll sum = 0 ;
        memset(head , -1 , sizeof(head)) ;
        nedge = 0 ;
        for(int i = 1;i <= n;i++)
        {
            ll a , b  ;int num ;
            scanf("%d" , &num) ;
            for(int j = 1;j <= num;j++)
            {
                scanf("%lld%lld%d" , &a , &b , &m) ;
                ll w = (ll)(b - a) ;
                if(w > 0)
                {
                    sum += w ;
                    addedge(st , i*25+j , w) ;
                }
                else addedge(i*25+j , en , -w) ;
                while(m--)
                {
                    int u , v ;
                    scanf("%d%d" , &u , &v) ;
                    addedge(i*25+j , u*25+v , inf) ;
                }
            }
        }
        ll ans = 0 ;ll res ;
        while(bfs())
          while(res = dfs(st , inf))
            ans += res ;
        printf("Case #%d: " , ++cas) ;
        printf("%lld\n" , sum - ans) ;
    }
    return 0 ;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

hdu3996Gold Mine 最小割

标签:

原文地址:http://blog.csdn.net/cq_pf/article/details/47724457

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