zoukankan      html  css  js  c++  java
  • 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
    ", anser);
            }
            return 0;
    }
  • 相关阅读:
    支付宝接口相关整理
    诡异的 &quot;password取回&quot; 邮件问题
    剑指 offer代码解析——面试题39推断平衡二叉树
    女程序猿做了个梦,各路大神惊现神级评论!
    Mac: Android studio+VirtualBox+Genymotion
    lua 中pairs 和 ipairs差别
    機器學習基石 (Machine Learning Foundations) 作业1 Q15-17的C++实现
    怎样获取HTML5视频的持续时间
    Android之本地相冊图片选取和拍照以及图片剪辑
    19_Android中图片处理原理篇,关于人脸识别站点,图片载入到内存,图片缩放,图片翻转倒置,网上撕衣服游戏案例编写
  • 原文地址:https://www.cnblogs.com/Aragaki/p/11166490.html
Copyright © 2011-2022 走看看