BZOJ1585 USACO 2009 Mar Gold 3.Earthquake Damage 2

题目大意:与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 20010
struct 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;
}


你可能感兴趣的:(BZOJ1585 USACO 2009 Mar Gold 3.Earthquake Damage 2)