【最小割】HDU 3251 Being a Hero

题意:给你了一个王国的地图

一个国王准备送你几座城市(每个城市都有个价值) 但是送你的超市不能和首都相连

所以要摧毁掉一些道路(毁路需要花费值)使得所选的城市不与首都相连;

求(所选的城市的值-毁路花费的值)最大;

并输出毁哪几条边;


建图:以首都1点为源点 建一个汇点

能选的城市指向汇点 权值为这个城市的价值

即maxans=可选城市的价值和-最大流得到的值;

输出删掉的边可跑一次dfs或者bfs,标记在图上可到达的点



#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <math.h>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#include <functional>
using namespace std;
#define LL __int64
#define ll long long
#define INF 999999999
#define MOD 1000000007

#define in freopen("c:\\users\\mfmy\\desktop\\input.txt", "r", stdin)
#define out freopen("c:\\users\\mfmy\\desktop\\output.txt", "w", stdout)

const int maxn = 1000000 + 5;

struct Edge
{
	int from, to, cap,flow, next;
}edge[maxn * 2];

struct Road
{
	int s, t;
}road[maxn];

int n, m, f, s, t, tol;
int head[1005];
bool vis[1005];
int ans[1111];
int gap[1111],dep[1111],cur[1111];
void addedge (int u,int v,int w,int rw = 0)
{
    edge[tol].to = v; edge[tol].cap = w; edge[tol].flow = 0;
    edge[tol].next = head[u]; head[u] = tol++;
    edge[tol].to = u; edge[tol].cap = rw; edge[tol].flow = 0;
    edge[tol].next = head[v]; head[v] = tol++;
}
int Q[maxn];
void init()
{
	memset(head, -1, sizeof(head));
	memset(vis, false, sizeof(vis));
	tol = 0, s = 1, t = n + 1;
}
void BFS(int start,int end)
{
    memset(dep,-1,sizeof(dep));
    memset(gap,0,sizeof(gap));
    gap[0] = 1;
    int front = 0, rear = 0;
    dep[end] = 0;
    Q[rear++] = end;
    while(front != rear)
    {
        int u = Q[front++];
        for(int i = head[u]; i !=  -1; i = edge[i].next)
        {
            int v = edge[i]. to;
            if(dep[v] != -1)continue;
            Q[rear++] = v;
            dep[v] = dep[u] + 1;
            gap[dep[v]]++;
        }
    }
}
int S[maxn];
int sap(int start,int end, int N)
{
    BFS(start,end);
    memcpy(cur,head,sizeof(head));
    int top = 0;
    int u = start;
    int ans = 0;
    int i;
    while(dep[start] < N)
    {
        if(u == end)
        {
            int Min = INF;
            int inser;
            for( i = 0;i < top;i++)
            {
                if(Min > edge[S[i]].cap - edge[S[i]].flow)
                {
                    Min = edge[S[i]].cap - edge[S[i]].flow;
                    inser = i;
                }
            }
            for( i = 0;i < top;i++)
            {
                edge[S[i]]. flow += Min;
                edge[S[i]^1].flow -= Min;
            }
            ans += Min;
            top = inser;
            u = edge[S[top]^1].to;
            continue;
        }
        bool flag =  false;
        int v;
        for( i = cur[u]; i != -1; i = edge[i]. next)
        {
            v = edge[i]. to;
            if(edge[i].cap - edge[i].flow && dep[v]+1 == dep[u])
            {
                flag =  true;
                cur[u] = i;
                break;
            }
        }
        if(flag)
        {
            S[top++] = cur[u];
            u = v;
            continue;
        }
        int Min = N;
        for( i = head[u]; i !=  -1; i = edge[i].next)
        {
            if(edge[i].cap - edge[i].flow && dep[edge[i].to] < Min)
            {
                Min = dep[edge[i].to];
                cur[u] = i;
            }
        }
        gap[dep[u]]--;
        if(!gap[dep[u]]) return ans;
        dep[u] = Min + 1;
        gap[dep[u]]++;
        if(u != start)u = edge[S[--top]^1].to;
    }
    return ans;
}

void solve(int u)
{
	vis[u] = true;
	for(int i = head[u]; i != -1; i = edge[i].next)
	{
		int v = edge[i].to;
		if(!vis[v] && edge[i].cap > edge[i].flow)
		{
			solve(v);
		}
	}
}

int main()
{
	int T;
	//freopen ("in.txt" , "r" , stdin);
	scanf("%d", &T);
	for(int Case = 1; Case <= T; Case++)
	{
		scanf("%d%d%d", &n, &m, &f);
		init();
		for(int i = 1; i <= m; i++)
		{
			int u, v, p;
			scanf("%d%d%d", &u, &v, &p);
			road[i].s = u, road[i].t = v;
			addedge(u, v, p);
		}
		int sum = 0;
		for(int i = 1; i <= f; i++)
		{
			int u, p;
			scanf("%d%d", &u, &p);
			addedge(u, t, p);
			sum += p;
		}
		printf("Case %d: %d\n", Case, sum - sap(s, t,n+1));
		solve(s);
		int cnt = 0;
		for(int i = 1; i <= m; i++)
		{
			if(vis[road[i].s] && !vis[road[i].t])
				ans[cnt++] = i;
		}
		printf("%d", cnt);
		for(int i = 0; i < cnt; i++)
			printf(" %d", ans[i]);
		printf("\n");
	}
	return 0;
}


posted @ 2014-08-18 10:03  kewowlo  阅读(214)  评论(0编辑  收藏  举报