zoukankan      html  css  js  c++  java
  • AcWing

    https://www.acwing.com/problem/content/259/

    这道题蛮有趣的。

    思路之一,是边带权并查集,相当于给点黑白染色,经过一条边权为1的边则改变一次颜色,规定到根节点边权和为0的为黑色。这样做的时候需要注意,合并两个不同并查集的x,y的时候,需要注意现在的黑白色只是当前连通块以内的颜色,当某次操作需要把两个不同连通块之间的黑色连在一起,则边权要带1,使子树的颜色全部翻转。

    更简单的思路是,为每个人维护一个“对方集合”代表元素,每次把x,y合并的时候,假如x的“对方集合”为空则把y作为“对方集合”的第一个元素,否则把y和x的“对方集合”合并。假如某次要合并的x,y本身就在同一个集合中,直接false。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    int fa[20005];
    bool d[20005];
    
    int find(int x) {
        if(x == fa[x])
            return x;
        int rt = find(fa[x]);
        d[x] ^= d[fa[x]];
        return fa[x] = rt;
    }
    
    void merge(int x, int y) {
        int fx = find(x);
        int fy = find(y);
        if(d[x] == d[y])
            d[fx] ^= 1;
        fa[fx] = fy;
    }
    
    bool check(int x, int y) {
        int fx = find(x);
        int fy = find(y);
        if(fx == fy) {
            if(d[x] == d[y])
                return false;
            return true;
        }
        merge(x, y);
        return true;
    }
    
    struct Edge {
        int u, v, w;
        bool operator<(const Edge &e)const {
            return w > e.w;
        }
    } edge[100005];
    
    int main() {
    #ifdef Yinku
        freopen("Yinku.in", "r", stdin);
    #endif // Yinku
        int n;
        scanf("%d", &n);
        for(int i = 1; i <= n; ++i) {
            fa[i] = i;
            d[i] = 0;
        }
        int m;
        scanf("%d", &m);
        for(int i = 1; i <= m; ++i) {
            scanf("%d%d%d", &edge[i].u, &edge[i].v, &edge[i].w);
        }
        sort(edge + 1, edge + 1 + m);
        bool put = 0;
        for(int i = 1; i <= m; ++i) {
            if(check(edge[i].u, edge[i].v)) {
                //printf("%d %d %d
    ", edge[i].u, edge[i].v, edge[i].w);
            } else {
                put = 1;
                printf("%d
    ", edge[i].w);
                break;
            }
        }
        if(!put)
            puts("0");
    }
    
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    int fa[20005];
    int enemy[20005];
    
    int find(int x) {
        if(x == fa[x])
            return x;
        return fa[x] = find(fa[x]);
    }
    
    void merge(int x, int y) {
        int fx = find(x);
        int fy = find(y);
        fa[fx] = fy;
    }
    
    bool check(int x, int y) {
        int fx = find(x);
        int fy = find(y);
        if(fx == fy)
            return false;
        else {
            if(enemy[fx] == 0)
                enemy[fx] = fy;
            else
                merge(enemy[fx], fy);
            if(enemy[fy] == 0)
                enemy[fy] = fx;
            else
                merge(enemy[fy], fx);
            return true;
        }
    }
    
    struct Edge {
        int u, v, w;
        bool operator<(const Edge &e)const {
            return w > e.w;
        }
    } edge[100005];
    
    int main() {
    #ifdef Yinku
        freopen("Yinku.in", "r", stdin);
    #endif // Yinku
        int n;
        scanf("%d", &n);
        for(int i = 1; i <= n; ++i) {
            fa[i] = i;
            enemy[i] = 0;
        }
        int m;
        scanf("%d", &m);
        for(int i = 1; i <= m; ++i) {
            scanf("%d%d%d", &edge[i].u, &edge[i].v, &edge[i].w);
        }
        sort(edge + 1, edge + 1 + m);
        bool put = 0;
        for(int i = 1; i <= m; ++i) {
            if(check(edge[i].u, edge[i].v)) {
                //printf("%d %d %d
    ", edge[i].u, edge[i].v, edge[i].w);
            } else {
                put = 1;
                printf("%d
    ", edge[i].w);
                break;
            }
        }
        if(!put)
            puts("0");
    }
    
  • 相关阅读:
    文件操作:根据现有类生成所需要的类
    Microsoft JScript 运行时错误: “”未定义
    未完成
    WPF模拟雷达界面效果图
    WebClient模拟网页提交表单
    201319
    Delphi中的InStrRev函数(倒找文本)
    利用IDhttp实现图片下载
    白话解释哈希表
    整理的Delphi常用字符串函数
  • 原文地址:https://www.cnblogs.com/Inko/p/11423730.html
Copyright © 2011-2022 走看看