zoukankan      html  css  js  c++  java
  • [欧拉回路] CF209C Trails and Glades

    填个远古的巨坑。。。。
    主要是这题和当年考的题题面有点出入不然早改好直接交

    码风比较远古

    /*
    并查集维护连通块
    跑一遍图
    记录每个点度数需
    要加的边数为 
    (偶数度数连通块数) + (奇数度数点数) / 2 -> 多个连通块时
    或
    (奇数点数个数) / 2 -> 单个连通块时
    注意可能有重边和自环 -> 这题和模拟赛不同,它只要求存在欧拉回路
        百度学长
        如果图G中的一个路径包括每个边恰好一次,则该路径称为欧拉路径(Euler path)。
        如果一个回路是欧拉路径,则称为欧拉回路(Euler circuit)。
    也就是说欧拉回路不需要考虑单独的点
    但是自环的点还是要考虑的
    */
    
    # include <iostream>
    # include <cstdio>
    # include <cstring>
    
    using namespace std;
    
    # define MAXN 1000005
    
    int n, m, degree[MAXN];
    bool vis[MAXN];
    // Union-Find Set
    
    int sum[MAXN];
    
    int size[MAXN], fa[MAXN];
    
    void init_ufs(int x){
        memset(vis, 0 ,sizeof(vis));
        for(int i = 1; i <= n; i++){
            size[i] = 1;
            fa[i] = i;
        }
    }
    
    int find(int x){
        return fa[x] == x ? x : fa[x] = find(fa[x]);
    }
    
    void merge(int x, int y){
        x = find(x);
        y = find(y);
        if(x == y) return;
        if(size[x] > size[y]){
            fa[y] = x;
            size[x] += size[y];
        }
        else{
            fa[x] = y;
            size[y] += size[x];
        }
    }
    
    // Main Function
    
    int main(){
        int a, b;
        scanf("%d%d", &n, &m);
        init_ufs(n);
        vis[1] = 1; // 注意! //////////
    
        for(int i = 1; i <= m; i++){
            scanf("%d%d", &a, &b);
            degree[a]++, degree[b]++;
    
            a = find(a), b = find(b);
    
            if(a != b)
                merge(a, b);
    
            vis[size[a] > size[b] ? a : b] = 1;
        }
    
        int cnt = 0, ans = 0;
    
        for(int i = 1; i <= n; i++){
            if(i == find(i) && vis[find(i)]){
                cnt += 1;
            }
        }
    
        if(!vis[find(1)]){
            cnt += 1; // 注意和模拟赛不同的是这题要求必须过一号节点
        }
    
        for(int i = 1; i <= n; i++){
            if(degree[i] % 2){
                sum[find(i)] += 1;
            }
        }
    
        if(cnt == 1){
            cout<<sum[find(1)] / 2;
            return 0;
        }
    
        for(int i = 1; i <= n; i++){
            if(vis[i] && find(i) == i){
                ans += sum[i] / 2;
                if(!sum[i]){
                    ans += 1;
                }
            }
        }    
    
        cout<<ans;
    
        return 0;
    }
    
    
  • 相关阅读:
    EduCF-69 Array Splitting (连续子序列,规律)
    Subsequence 单调队列
    HDU
    HDU
    Numpy 切片和索引
    Numpy 从数值范围创建数组
    Numpy 的常用属性 和创建数组
    Numpy 线性代数
    Numpy 矩阵库(Matrix)
    Numpy 创建数组
  • 原文地址:https://www.cnblogs.com/Foggy-Forest/p/13387950.html
Copyright © 2011-2022 走看看