【最大流】HDU 5352 MZL's City

通道

题意:3种操作,加点,加边,删边,然后对于每次加点操作为不超过k个点,求对于每次加点时加点数量的方案的字典序最小。

思路:

要保证字典序最小,就倒着来,能加的都加进去。

建图方法就是拆点,源点向i建流量为k,tot+i到汇点建流量为1,i到tot+v建流量为1.

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

typedef long long ll;

const int MAX_N = 407;
const int MAX_E = MAX_N * MAX_N * 5;
const int INF = 0x3f3f3f3f;

struct Edge {
    int v, nxt;
    ll cap;
    Edge() {

    }
    Edge(int _v, int _nxt, ll _cap) {
        v = _v, nxt = _nxt, cap = _cap;
    }
};

struct Isap {
    Edge G[MAX_E];
    int edgecnt, head[MAX_N];
    int gap[MAX_N], d[MAX_N];
    int n, s, t;
    void init(int n, int s, int t) {
        this->n = n, this->s = s, this->t = t;
        edgecnt = 0;
        memset(head, -1, sizeof head);
    }
    void add(int u, int v, ll cap) {
        G[edgecnt] = Edge(v, head[u], cap);
        head[u] = edgecnt++;
        G[edgecnt] = Edge(u, head[v], 0);
        head[v] = edgecnt++;
    }
    ll dfs(int u, ll tot) {
        if (u == t) return tot;
        int minh = n - 1;
        ll leave = tot;
        for (int i = head[u]; ~i && leave; i = G[i].nxt) {
            int v = G[i].v;
            if (G[i].cap > 0) {
                if (d[v] + 1 == d[u]) {
                    ll c = dfs(v, min(leave, G[i].cap));
                    G[i].cap -= c;
                    G[i ^ 1].cap += c;
                    leave -= c;
                    if (d[s] >= n) 
                        return tot - leave;
                }
                minh = min(minh, d[v]);
            }
        }
        if (leave == tot) {
            --gap[d[u]];
            if (gap[d[u]] == 0) d[s] = n;
            d[u] = minh + 1;
            ++gap[d[u]];
        }
        return tot - leave;
    }
    ll maxFlow() {
        ll ret = 0;
        memset(gap, 0, sizeof gap);
        memset(d, 0, sizeof d);
        gap[0] = n;
        while (d[s] < n) {
            ret += dfs(s, INF);
        }
        return ret;
    }
};

int n, m, k;
int head[MAX_N], edgecnt;
Edge G[MAX_E];
bool dep[507][MAX_N], g[MAX_N][MAX_N];
Isap Flow;
int ans[MAX_N];

void Clear() {
    memset(head, -1, sizeof head); edgecnt = 0;    
    for (int i = 0; i <= m; ++i)
        for (int j = 0; j <= n; ++j)
            dep[i][j] = false;
    for (int i = 0; i <= n; ++i)
        for (int j = 0; j <= n; ++j)
            g[i][j] = 0;
}
void add(int u, int v) {
    G[edgecnt] = Edge(v, head[u], 0);
    head[u] = edgecnt++;
}

void dfs(int id, int u) {
    add(id, u);
    dep[id][u] = true;
    for (int v = 1; v <= n; ++v) {
        if (!g[u][v] || dep[id][v]) continue;
        dfs(id, v);
    }
}

int cal(int tot) {
    int s = 0, t = tot + n + 1;
    Flow.init(tot + n + 2, s, t);
    for (int i = 1; i <= tot; ++i) Flow.add(s, i, k);
    for (int i = 1; i <= n; ++i) Flow.add(tot + i, t, 1);
    ll ret = 0;
    for (int i = tot; i >= 1; --i) {
        for (int j = head[i]; ~j; j = G[j].nxt) {
            int v = G[j].v;
            Flow.add(i, tot + v, 1);
        }
        ret += Flow.maxFlow();
    }
    for (int i = Flow.head[s]; ~i; i = Flow.G[i].nxt) {
        int v = Flow.G[i].v;
        ans[v] = Flow.G[i ^ 1].cap;
    }
    return ret;
}

template <class T>
inline bool rd(T &ret) {
    char c; int sgn;
    if(c = getchar() , c == EOF) return false;
    while(c != '-' && (c < '0' || c > '9')) c = getchar();
    sgn = (c == '-') ? -1 : 1;
    ret = (c == '-') ? 0 : (c - '0');
    while(c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
    ret *= sgn;
    return true;
}

int main() {
    int T;
    scanf("%d", &T);
    while (T-- > 0) {
        Clear();
        rd(n), rd(m), rd(k);
        int tot = 0;
        for (int i = 1; i <= m; ++i) {
            int type; rd(type);
            if (1 == type) {
                int x; rd(x);
                dfs(++tot, x);
            } else if (2 == type) {
                int u, v; rd(u), rd(v);
                g[u][v] = g[v][u] = true;
            } else {
                int x; rd(x);
                while (x-- > 0) {
                    int u, v; rd(u), rd(v);
                    g[u][v] = g[v][u] = false;
                }
            }
        }
        for (int i = 1; i <= tot; ++i) ans[i] = k;
        int maxFlow = cal(tot);
        printf("%d\n", maxFlow);
        for (int i = 1; i <= tot; ++i) 
            printf("%d%c", ans[i], i == tot ? '\n' : ' ');
    }
    return 0;
}
View Code

 

posted @ 2015-08-04 20:00  mithrilhan  阅读(190)  评论(0编辑  收藏  举报