SCU 4442 party 二分图最大点权独立集

每个青蛙喝黑茶或者红茶或者都可以喝

M个矛盾关系 有矛盾的不能喝同种茶 但你可以花费Wi使得这个青蛙消除所有矛盾 把矛盾当作边 青蛙当作点 如果这两个青蛙只喝不同的一种茶就不建边

题目中保证了不存在奇环 可以黑白染色成二分图

然后把两个茶都可以喝的青蛙拆点 u表示该青蛙喝黑茶 u+n表示喝红茶 同时建边(u,u+n)

有四种情况:

1.两个青蛙都可以喝两种茶 建边(u,v) (u+n,v+n)

2.两个青蛙一个可以喝两种茶 一个可以喝黑茶 建边(u,v)

3.两个青蛙一个可以喝两种茶 一个可以喝红茶 建边(u,v+n)

4.两种青蛙都只能喝一种茶 建边(u,v)

然后黑白染色成二分图连S,T 跑二分图最小点权覆盖集

最后跑出来的答案要减去sumw 因为两种茶都可以喝的青蛙拆点导致每次拆点多花费了Wi

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 3050;
const int MAXM = 100000;
const int INF = 1000000005;
int Head[MAXN], cur[MAXN], lev[MAXN], to[MAXM << 1], nxt[MAXM << 1], f[MAXM << 1], ed, S, T;
int n, m;
inline void addedge(int u, int v, int cap) {
        to[++ed] = v;
        nxt[ed] = Head[u];
        Head[u] = ed;
        f[ed] = cap;
        to[++ed] = u;
        nxt[ed] = Head[v];
        Head[v] = ed;
        f[ed] = 0;
        return ;
}
inline bool BFS() {
        int u;
        memset(lev, -1, sizeof(lev));
        queue<int> q;
        lev[S] = 0;
        q.push(S);
        while (q.size()) {
                u = q.front();
                q.pop();
                for (int i = Head[u]; i; i = nxt[i]) {
                        if (f[i] && lev[to[i]] == -1) {
                                lev[to[i]] = lev[u] + 1;
                                q.push(to[i]);
                        }
                }
        }
        memcpy(cur, Head, sizeof(Head));
        return lev[T] != -1;
}
inline int DFS(int u, int maxf) {
        if (u == T || !maxf) {
                return maxf;
        }
        int cnt = 0;
        for (int &i = cur[u], tem; i; i = nxt[i]) {
                if (f[i] && lev[to[i]] == lev[u] + 1) {
                        tem = DFS(to[i], min(maxf, f[i]));
                        maxf -= tem;
                        f[i] -= tem;
                        f[i ^ 1] += tem;
                        cnt += tem;
                        if (!maxf) {
                                break;
                        }
                }
        }
        if (!cnt) {
                lev[u] = -1;
        }
        return cnt;
}
int Dinic() {
        int ans = 0;
        while (BFS()) {
                ans += DFS(S, 2147483647);
        }
        return ans;
}
void init(int SS, int TT) {
        memset(Head, 0, sizeof(Head));
        ed = 1;
        S = SS, T = TT;
        return ;
}
struct node {
        int kind;
        int id;
        int l, r;
        int w;
} frog[2005];
vector<int> g[2 * MAXN];
int color[2 * MAXN];
int sumw;
void dfs(int x, int pre) {
        for (int v : g[x]) {
                if (v == pre || color[v] != -1) {
                        continue;
                }
                color[v] = color[x] ^ 1;
                dfs(v, x);
        }
}
inline void add(int u, int v) {
        g[u].push_back(v);
        g[v].push_back(u);
}
int main() {
        int u, v;
        while (scanf("%d %d", &n, &m) != -1) {
                sumw = 0;
                for (int i = 1; i <= 2 * n; i++) {
                        color[i] = -1;
                        g[i].clear();
                }
                for (int i = 1; i <= n; i++) {
                        scanf("%d", &frog[i].w);
                }
                for (int i = 1; i <= n; i++) {
                        scanf("%d", &frog[i].kind);
                        if (frog[i].kind == 3) {
                                sumw += frog[i].w;
                                add(i, i + n);
                        }
                }
                for (int i = 1; i <= m; i++) {
                        scanf("%d %d", &u, &v);
                        if (frog[u].kind + frog[v].kind == 3) {
                                continue;
                        }
                        if (frog[u].kind > frog[v].kind) {
                                swap(u, v);
                        }
                        if (frog[u].kind != 3) {
                                if (frog[v].kind != 3) {
                                        add(u, v);
                                } else {
                                        if (frog[u].kind == 1) {
                                                add(u, v);
                                        } else {
                                                add(u, v + n);
                                        }
                                }
                        } else {
                                add(u, v);
                                add(u + n, v + n);
                        }
                }
                for (int i = 1; i <= 2 * n; i++) {
                        if (color[i] == -1) {
                                color[i] = 0;
                                dfs(i, -1);
                        }
                }
                init(0, 2 * n + 1);
                for (int i = 1; i <= 2 * n; i++) {
                        int wnow;
                        if (i > n) {
                                wnow = frog[i - n].w;
                        } else {
                                wnow = frog[i].w;
                        }
                        if (color[i] == 0) {
                                addedge(S, i, wnow);
                        } else {
                                addedge(i, T, wnow);
                        }
                }
                for (int i = 1; i <= 2 * n; i++) {
                        if (color[i] == 0) {
                                for (int v : g[i]) {
                                        addedge(i, v, INF);
                                }
                        }
                }
                int anser = Dinic();
                anser -= sumw;
                printf("%d\n", anser);
        }
        return 0;
}

 

posted @ 2019-07-10 21:01  Aragaki  阅读(212)  评论(0)    收藏  举报