Codeforces 687D Dividing Kingdom II (图论+并查集)

来源:互联网 发布:dnspod和阿里云解析 编辑:程序博客网 时间:2024/06/04 01:00

题意:

给你一张图,其中边按照序号排好,每次给你一个 l和r,让你用给定区间范围内的边生成一张图,然后把这个图中的点分成两边,在所有使用的边中,使得两边端点在同一个部分的边的最大值最小。

解法:

我们可以很快的看出,如果是二分图的话,那么所有的边的两个端点都不会再同一个部分,那么也就是说如果生成的图不是二分图,那么才会存在这样的边,于是问题就转变成了如何找到所有的奇环的最小边的最大值。这里可以用并查集来找到所有的奇环。我们把边按权重降序排好之后,第一个碰到的奇环的那条边就是答案。至于并查集如何判断奇环,我们需要把每一个点拆成两个点,每次合并时,都是合并的拆出的点,具体看代码。

//  Created by  CQU_CST_WuErli//  Copyright (c) 2016 CQU_CST_WuErli. All rights reserved.////#pragma comment(linker, "/STACK:102400000,102400000")#include <iostream>#include <cstring>#include <cstdio>#include <cstdlib>#include <cctype>#include <cmath>#include <string>#include <vector>#include <map>#include <queue>#include <stack>#include <set>#include <algorithm>#include <sstream>#define CLR(x) memset(x,0,sizeof(x))#define OFF(x) memset(x,-1,sizeof(x))#define MEM(x,a) memset((x),(a),sizeof(x))#define BUG cout << "I am here" << endl#define lookln(x) cout << #x << "=" << x << endl#define SI(a) scanf("%d", &a)#define SII(a,b) scanf("%d%d", &a, &b)#define SIII(a,b,c) scanf("%d%d%d", &a, &b, &c)const int INF_INT=0x3f3f3f3f;const long long INF_LL=0x7f7f7f7f;const int MOD=1e9+7;const double eps=1e-10;const double pi=acos(-1);typedef long long  ll;using namespace std;int n, q, m;struct Edge {    int u, v, w, id;    Edge(int u, int v, int w, int id):u(u), v(v), w(w), id(id) {}    Edge() {}    bool operator < (const Edge& rhs) const {        return w < rhs.w;    }};vector<Edge> es;int par[1010 << 1], rnk[1010 << 1];void init() {    for (int i = 1; i <= 2 * n; i++) par[i] = i, rnk[i] = 0;}int find(int x) {    if (par[x] == x) return x;    else return par[x] = find(par[x]);}bool same(int x, int y) {    return find(x) == find(y);}void unite(int x, int y) {    x = find(x), y = find(y);    if (x == y) return;    if (rnk[x] < rnk[y]) par[x] = y;    else {        par[y] = x;        if (rnk[x] == rnk[y]) rnk[x]++;    }}int query(int l, int r) {    init();    for (int i = es.size() - 1; i >= 0; i--) {        Edge& e = es[i];        if (e.id < l || e.id > r) continue;        if (!same(e.u, e.v)) {            unite(e.u, e.v + n);            unite(e.u + n, e.v);        }        else return e.w;    }    return -1;}int main(int argc, char const *argv[]) {#ifdef LOCAL    freopen("C:\\Users\\john\\Desktop\\in.txt","r",stdin);    // freopen("C:\\Users\\john\\Desktop\\out.txt","w",stdout);#endif    while(SIII(n, m, q) == 3) {        es.clear();        for (int i = 1; i <= m; i++) {            int u, v, w;            SIII(u, v, w);            es.push_back(Edge(u, v, w, i));        }        sort(es.begin(), es.end());        int l, r;        while(q--) {            SII(l, r);            printf("%d\n", query(l, r));        }    }    return 0;}
0 0
原创粉丝点击