BZOJ1585 USACO 2009 Mar Gold 3.Earthquake Damage 2

来源:互联网 发布:58同城淘宝网 编辑:程序博客网 时间:2024/05/22 08:03

题目大意:与http://blog.csdn.net/wyfcyx_forever/article/details/39345281这个相近。只是求的是损坏节点的最小数目。


Sol:

拆点最小割。

S->1 c=INF

提到的点x x'->T c=INF

对于每个点x,为1或是提到的点 x->x' c=INF

对于每个点x,不为1且不是提到的点 x->x' c=1

对于原图每条边x->y x'->y c=INF y'->x c=INF

然后强大的ISAP模板水过。


Code:

#include <queue>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std; #define INF 0x3f3f3f3f queue<int> q; #define N 3010#define M 20010struct Solver {    int head[N << 1], next[(M << 2) + N*2], end[(M << 2) + N*2], flow[(M << 2) + N*2], ind;    int gap[N << 1], stack[N << 1], top, cur[N << 1], d[N << 1];    void reset() {        ind = top = 0;        memset(head, -1, sizeof(head));    }    void addedge(int a, int b, int _flow) {        int q = ind++;        end[q] = b;        next[q] = head[a];        head[a] = q;        flow[q] = _flow;    }    void make(int a, int b, int _flow) {        //printf("%d %d %d\n", a, b, _flow);        addedge(a, b, _flow);        addedge(b, a, 0);    }    void make_db(int a, int b, int _flow) {        addedge(a, b, _flow);        addedge(b, a, _flow);    }    void bfs(int T) {        memset(gap, 0, sizeof(gap));        memset(d, -1, sizeof(d));        ++gap[d[T] = 0];        q.push(T);        int i, j;        while(!q.empty()) {            i = q.front();            q.pop();            for(j = head[i]; j != -1; j = next[j])                if (d[end[j]] == -1) {                    ++gap[d[end[j]] = d[i] + 1];                    q.push(end[j]);                }        }    }    int Maxflow(int S, int T) {        bfs(T);        memcpy(cur, head, sizeof(cur));        int u = S, res = 0, Min, ins, i;        bool find;        while(d[S] < T - S + 1) {            if (u == T) {                Min = INF;                for(i = 0; i < top; ++i)                    if (Min > flow[stack[i]])                        Min = flow[stack[i]], ins = i;                for(i = 0; i < top; ++i)                    flow[stack[i]] -= Min, flow[stack[i] ^ 1] += Min;                res += Min;                u = end[stack[top = ins] ^ 1];            }            if (u != T && !gap[d[u] - 1])                break;            find = 0;            for(int &j = cur[u]; j != -1; j = next[j])                if (flow[j] && d[end[j]] + 1 == d[u]) {                    ins = j;                    find = 1;                    break;                }            if (find) {                stack[top++] = ins;                cur[u] = ins;                u = end[ins];            }            else {                Min = T - S + 1;                for(int j = head[u]; j != -1; j = next[j])                    if (flow[j] && d[end[j]] < Min) {                        Min = d[end[j]];                        cur[u] = j;                    }                if (!--gap[d[u]])                    break;                ++gap[d[u] = Min + 1];                if (u != S)                    u = end[stack[--top] ^ 1];            }        }        return res;    }}G; int get[N]; int main() {    int n, m, num;    scanf("%d%d%d", &n, &m, &num);         int a, b, x;    register int i, j;    G.reset();    G.make(0, 1, INF);    for(i = 1; i <= m; ++i) {        scanf("%d%d", &a, &b);        G.make(a * 2, b * 2 - 1, INF);        G.make(b * 2, a * 2 - 1, INF);    }    while(num--) {        scanf("%d", &x);        get[x] = 1;    }    G.make(1, 2, INF);    for(i = 2; i <= n; ++i) {        if (!get[i])            G.make(2 * i - 1, 2 * i, 1);        else            G.make(2 * i - 1, 2 * i, INF), G.make(2 * i, 2 * n + 1, INF);    }    printf("%d", G.Maxflow(0, 2 * n + 1));         return 0;}


0 0
原创粉丝点击