HDU 3996 Gold Mine(最大权闭合图)

来源:互联网 发布:服务器如何开放端口 编辑:程序博客网 时间:2024/05/21 09:49

题目地址
题意:题意还是蛮复杂的,但是好好分析起来就好了,先告诉你有T组样例,然后每个样例里面有n个区域(n<=100),然后呢?每个区域里面都有m个金矿(m<=25)(其实我觉得直接看金矿就好了,标号就设为 i*26+j),然后告诉你每个金矿要花掉的钱以及能赚到的钱,以及与多少个金矿有关系,然后c行就是有关系金矿的区域号以及区域里面第几个金矿了(按之前的公式算就好了)。问最大的收益是多少?
思路:上面建图已经讲过了,还是就是按照最大权闭合图的建图方法去建(对于那个为什么明明是后面的是要采到才能采当前的建边为什么是从当前到那个点,我在这篇博客已经讲的很详细看),然后有一个优化就是先把赚到的减去花费的,如果为正的话就建s->当前,否则为当前->t,这样的话就可以减少建边条数,节省空间。
注意:数据比较大,一定要用LL求流量,inf要设置LL的inf

如果最大权闭合图不理解的话,可以戳这里。

#include <iostream>#include <cstring>#include <string>#include <queue>#include <vector>#include <map>#include <set>#include <stack>#include <cmath>#include <cstdio>#include <algorithm>#include <iomanip>#define N 3100#define M 555005  #define LL __int64#define inf 0x3f3f3f3f3f3f3f3f#define lson l,mid,ans<<1#define rson mid+1,r,ans<<1|1#define getMid (l+r)>>1#define movel ans<<1#define mover ans<<1|1using namespace std;const LL mod = 1000000007;int head[N], level[N], cur[N];int n, m, cnt;struct node {    int to;    LL cap;//剩余流量    int next;}edge[M];struct Dinic {    void init() {        memset(head, -1, sizeof(head));        cnt = 0;    }    void add(int u, int v, LL cap) {//有向图        edge[cnt].to = v, edge[cnt].cap = cap, edge[cnt].next = head[u], head[u] = cnt++;        edge[cnt].to = u, edge[cnt].cap = 0, edge[cnt].next = head[v], head[v] = cnt++;//反向边    }    bool bfs(int s, int t){        memset(level, -1, sizeof(level));        queue<int>Q;        level[s] = 0;        Q.push(s);        while (!Q.empty()){            int u = Q.front(); Q.pop();            for (int i = head[u]; i + 1; i = edge[i].next){                int v = edge[i].to;                if (edge[i].cap>0 && level[v] == -1){                    level[v] = level[u] + 1;                    Q.push(v);                }            }        }        return level[t] != -1;    }    LL dfs(int u, int t, LL f){        if (u == t) return f;        for (int &i = cur[u]; i + 1; i = edge[i].next){            int v = edge[i].to;            if (edge[i].cap>0 && level[v] == level[u] + 1){                LL d = dfs(v, t, min(f, edge[i].cap));                if (d>0){                    edge[i].cap -= d;                    edge[i ^ 1].cap += d;                    return d;                }            }        }        return 0;    }    LL dinic(int s, int t){        LL flow = 0;        while (bfs(s, t)){            for (int i = 0; i<N; i++) cur[i] = head[i];            LL f;            while ((f = dfs(s, t, inf))>0)                flow += f;        }        return flow;    }}dc;int main() {    cin.sync_with_stdio(false);    LL a, b, c;    int s, t;    LL sum;    int T, Case = 1;    cin >> T;    while (T--) {        cin >> n;        dc.init();        sum = 0;        s = 0;        t = 3000;        for (int i = 1; i <= n; i++) {            cin >> m;            for (int j = 1; j <= m; j++) {                cin >> a >> b >> c;//a为要花的钱,b为赚到的钱                b -= a;                if (b > 0) {                    sum += b;                    dc.add(s, i * 26 + j, b);                }                else {                    dc.add(i * 26 + j, t, -b);                }                while (c--) {                    cin >> a >> b;                    dc.add(i * 26 + j, a * 26 + b, inf);                }            }        }        cout << "Case #" << Case++ << ": " << sum - dc.dinic(s, t) << endl;    }    return 0;}
阅读全文
0 0
原创粉丝点击