[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; }
skr