[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

猜你喜欢

转载自www.cnblogs.com/ckxkexing/p/11666555.html