[HDU 3521] [最小割] Being a Hero

题意:

在一个有向图中,有n个点,m条边$n \le 1000 \And \And  m \le 100000$

每条边有一个破坏的花费,有些点可以被选择并获得对应的金币。

假设一个可以选的点是$x$,你只有破坏了从1号点到$x$的路,才可以得到$x$对应的金币。

思路:

点和边的区别在于,你放弃一个点得到$0$,选择一个点得到$val$。你放弃选择一条边得到$0$,选择一条边得到 - $val$。

那么我们先把每个点的权值加到ans中,最够减去这个图的最小割即可。

由于要输出破坏边的方案,所以要dfs染色,又由于是有向边,所以破坏的边是起点属于s的边。

 

// #pragma GCC optimize(2)
// #pragma GCC optimize(3)
// #pragma GCC optimize(4)
#include <algorithm>
#include <iterator>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <iomanip>
#include <bitset>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <stack>
#include <cmath>
#include <queue>
#include <list>
#include <map>
#include <set>
#include <cassert>
//#include <unordered_set>
//#include <unordered_map>
// #include<bits/extc++.h>
// using namespace __gnu_pbds;
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr << #x << " := " << x << endl;
#define bug cerr << "-----------------------" << endl;
#define FOR(a, b, c) for (int a = b; a <= c; ++a)

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;

template <typename T>
inline T read(T &x) {
    x = 0;
    int f = 0;
    char ch = getchar();
    while (ch < '0' || ch > '9') f |= (ch == '-'), ch = getchar();
    while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar();
    return x = f ? -x : x;
}

/**********showtime************/
const int maxn = 1009;
int head[maxn], gtot = 0;
struct Edge {
    int u, v, w;
    int id;
    int nxt;
} edge[300009];

void addedge(int u, int v, int w, int id) {
    edge[gtot].u = u;
    edge[gtot].v = v;
    edge[gtot].w = w;
    edge[gtot].nxt = head[u];
    edge[gtot].id = id;
    head[u] = gtot++;

    edge[gtot].u = v;
    edge[gtot].v = u;
    edge[gtot].w = 0;
    edge[gtot].nxt = head[v];
    edge[gtot].id = 0;
    head[v] = gtot++;
}
int n, m, f;
vector<int> vec;
int cur[maxn], dis[maxn];
bool bfs(int s, int t) {
    for (int i = s; i <= t; i++) {
        cur[i] = head[i];
        dis[i] = inf;
    }
    dis[s] = 0;
    queue<int> que;
    que.push(s);
    while (!que.empty()) {
        int u = que.front();
        que.pop();
        for (int i = head[u]; ~i; i = edge[i].nxt) {
            int v = edge[i].v, w = edge[i].w;
            if (w > 0 && dis[v] > dis[u] + 1) {
                dis[v] = dis[u] + 1;
                que.push(v);
            }
        }
    }
    return dis[t] < inf;
}

int dfs(int u, int t, int maxflow) {
    if (u == t || maxflow == 0) return maxflow;
    for (int i = cur[u]; ~i; i = edge[i].nxt) {
        cur[u] = i;
        int v = edge[i].v, w = edge[i].w;
        if (w > 0 && dis[v] == dis[u] + 1) {
            int f = dfs(v, t, min(maxflow, w));
            if (f > 0) {
                edge[i].w -= f;
                edge[i ^ 1].w += f;
                return f;
            }
        }
    }
    return 0;
}

int dinic(int s, int t) {
    int flow = 0;
    while (bfs(s, t)) {
        while (int f = dfs(s, t, inf))
            flow += f;
    }
    return flow;
}

int col[maxn];
void colnode(int u) {
    col[u] = 1;
    for (int i = head[u]; ~i; i = edge[i].nxt) {
        int v = edge[i].v, w = edge[i].w;
        if (w && col[v] == 0) colnode(v);
    }
}

int main() {
    int T;
    scanf("%d", &T);
    int cas = 0;
    while (T--) {
        scanf("%d%d%d", &n, &m, &f);
        int s = 0, t = n + 1;
        for (int i = s; i <= t; i++) head[i] = -1, col[i] = 0;
        gtot = 0;

        for (int i = 1; i <= m; i++) {
            int u, v, w;
            scanf("%d%d%d", &u, &v, &w);
            addedge(u, v, w, i);
        }

        int sum = 0;
        addedge(s, 1, inf, 0);
        for (int i = 1; i <= f; i++) {
            int u, w;
            scanf("%d%d", &u, &w);
            addedge(u, t, w, 0);
            sum += w;
        }

        sum = sum - dinic(s, t);
        printf("Case %d: %d\n", ++cas, sum);
        colnode(s);
        vec.clear();
        for (int i = 0; i < gtot; i++) {
            int u = edge[i].u, v = edge[i].v, w = edge[i].w;
            int id = edge[i].id;
            if (col[u] == 1 && col[v] == 0 && id) {
                vec.pb(id);
            }
        }
        printf("%d", vec.size());
        //sort(vec.begin(), vec.end());
        for (int v : vec) {
            printf(" %d", v);
        }
        puts("");
    }
    return 0;
}
View Code
posted @ 2019-10-13 15:00  ckxkexing  阅读(210)  评论(0编辑  收藏  举报