2018 深圳CCPC final B. Balance of the Force 枚举最大值 + 线段树 + 二分图染色

题目链接:http://codeforces.com/gym/102055/problem/B

题意: 有两个种类, n个物品, 有m句话每句话都会说明那两个不是一个种类,且每个物品被当作每个种类的价值不一样。

问是否有案例成立,若成立求出案例中物品最大的价值与最小价值之差最小。

思路: 首先用染色法求是否成立。 然后缩点把每个连通块缩点,每个点就有两种方案,每个方案都有一个最大值和最小值,然后遍历从小到大的最大值,求可成立的最大的最小值。求最小值的时候可以用线段树维护即可。

ac代码:

#include <cstdio>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <string>
#include <cstring>
#include <queue>
#include <map>
#include <iterator>
#include <vector>
#define lc d<<1
#define rc d<<1|1
#define mid ((l+r)>>1)
using namespace std;
//typedef long long ll;
//template<class T> T maxx(T a, T b) {
//    return max(a, b);
//}
//template<class T, class ...R> T maxx(T a, R... b) {
//    return max(a, maxx(b...));
//}
//template<class T> T minn(T a, T b) {
//    return min(a, b);
//}
//template<class T, class ...R> T minn(T a, R... b) {
//    return min(a, minn(b...));
//}
const int mx = 2e5+5;
const int INF = 0x3f3f3f3f;
const int mod = 1e9+7;
int head[mx];
struct edge {
    int v, nex;
}E[2*mx];
int si;
void add(int u, int v) {
    E[si].v = v, E[si].nex = head[u];
    head[u] = si++;
}
//vector<int>ve[mx];
int cr[mx], a[2][mx];
int ma[mx][2], mi[mx][2];
struct noa {
    int id, a, fa;
    bool operator<(const noa &t) {
        return a<t.a;
    }
} N[2*mx];
//namespace T {
//    const int mx  =4e5+5;
struct tree {
    int mi;
    tree() {}
    tree(int mm):mi(mm) {}
    tree operator+(const tree &t) {
        return tree(min(t.mi, mi));
    }
} T[mx*4];

void pushup(int d) {///向上传
    T[d] = T[lc] + T[rc];
}

void build(int l, int r, int d) {///建树
    if (l == r) {
        T[d].mi = 0;
        return;
    }
    build(l, mid, lc);
    build(mid + 1, r, rc);
    pushup(d);
}
tree Query(int l, int r, int d, int x) {
    if (l == r)
        return T[d];
    if (mid < x)
        return Query(mid+1, r, rc, x);
    return Query(l, mid, lc, x);
}
void update(int l, int r, int d, int L, int x) {
    if (l == r) {
        T[d].mi = x;
        return;
    }
    if (mid < L)
        update(mid+1, r, rc, L, x);
    else
        update(l, mid, lc, L, x);
    pushup(d);
    return;
}
bool f;
int tot;
struct que{
    int fa, u, c;
    que() {}
    que(int ff, int uu, int cc):fa(ff), u(uu), c(cc) {}
}Q[mx+5];
inline void dfs(int fa, int u, int c) {
    if (f) return;
    int he = 0, fi = 0;
    Q[fi++] = que(fa, u, c);
    while (he < fi) {
        fa = Q[he].fa, u = Q[he].u, c = Q[he].c;
        he++;
        ma[tot][0] = max(ma[tot][0], a[c][u]);
        ma[tot][1] = max(ma[tot][1], a[c^1][u]);
        mi[tot][0] = min(mi[tot][0], a[c][u]);
        mi[tot][1] = min(mi[tot][1], a[c^1][u]);
        cr[u] = c;
        for (int i = head[u]; ~i; i = E[i].nex) {
            int v = E[i].v;
//            if (v == fa)
//                continue;
            if (cr[v] != -1 && cr[v] == c) {
                f = 1;
                return;
            }
//            dfs(u, v, c^1);
            if(cr[v] == -1)
                Q[fi++] = que(u, v, c^1);
        }
    }
    return;
}
void init(int n) {
    for (int i = 0; i <= n; ++i) {
        head[i] = -1;
        cr[i] = -1;
    }
    si = 0;
}
//using namespace T;
int main() {
    int n, m, q, k;
    int u, v;
    int i;
    scanf("%d", &q);
    for (int o = 1; o <= q; ++o) {
        printf("Case %d: ", o);
        scanf("%d%d", &n, &m);
        init(n);
        for (i = 0; i < m; ++i) {
            scanf("%d%d", &u, &v);
            add(u, v);
            add(v, u);
        }
        for (i = 1; i <= n; ++i)
            scanf("%d%d", &a[0][i], &a[1][i]);
        int ts = 0, mk = 0;
        tot = 0;
        f = 0;
        for (i = 1; i <= n; ++i) {
            if (cr[i] == -1) {
                ++tot;
                ma[tot][0] = ma[tot][1] = 0;
                mi[tot][0] = mi[tot][1] = INF;
                dfs(i, i, 0);
                mk = max(mk, min(ma[tot][0], ma[tot][1]));
                N[ts].fa = 0;
                N[ts].a = ma[tot][0];
                N[ts++].id = tot;
                N[ts].fa = 1;
                N[ts].a = ma[tot][1];
                N[ts++].id = tot;
            }
            if (f)break;
        }
        if (f) {
            puts("IMPOSSIBLE");
            continue;
        }
        build(1, tot, 1);
        sort(N, N+ts);
        int mix = INF;
        tree kx;
        for (i = 0; i < ts; ++i) {
            kx =Query(1, tot, 1, N[i].id);
            if (kx.mi < mi[N[i].id][N[i].fa]) {
                update(1, tot, 1, N[i].id, mi[N[i].id][N[i].fa]);
            }
            if (N[i].a < mk)
                continue;
            update(1, tot, 1, N[i].id, mi[N[i].id][N[i].fa]);
            mix = min(mix, N[i].a-T[1].mi);
            if (kx.mi > mi[N[i].id][N[i].fa])
                update(1, tot, 1, N[i].id, kx.mi);
        }
        printf("%d\n", mix);
    }
    return 0;
}
发布了74 篇原创文章 · 获赞 29 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/ClonH/article/details/103097048