• sgu 286. Ancient decoration(最小环覆盖)


    给你一个n个点,每个点度为k(k为偶数)的无向图,问是否能将图中的n条边染色,使得每个点都拥有两条被染色的边。也就是说,是否存在拥有原图中n条边的子图,使得每个点的度为2?仔细想想,每个点的度为2,实际上就是求原图的最小环覆盖了。

    求最小环覆盖的方法就是先求出原图的有向欧拉回路(k为偶数,欧拉回路必然存在),然后问题就转化成了是否能选择欧拉回路中的n条边,使得所有点都被覆盖?这不就转化成了DAG的最小路径覆盖了么!

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<fstream>
    #include<sstream>
    #include<bitset>
    #include<vector>
    #include<string>
    #include<cstdio>
    #include<cmath>
    #include<stack>
    #include<queue>
    #include<stack>
    #include<map>
    #include<set>
    #define FF(i, a, b) for(int i=a; i<b; i++)
    #define FD(i, a, b) for(int i=a; i>=b; i--)
    #define REP(i, n) for(int i=0; i<n; i++)
    #define CLR(a, b) memset(a, b, sizeof(a))
    #define debug puts("**debug**")
    #define LL long long
    #define PB push_back
    using namespace std;
    
    const int maxn = 1001;
    int g[maxn][maxn], degree[maxn], match[maxn], id[maxn][maxn];
    bool vis[maxn];
    int n, k, u, v;
    
    void Euler()
    {
        FF(i, 1, n+1) if(degree[i])
        {
            int u = i;
            while(true)
            {
                FF(j, 1, n+1) if(g[u][j] && g[j][u])
                {
                    g[j][u] = 0;
                    degree[u]--, degree[i]--;
                    u = j;
                    break;
                }
                if(u == i) break;
            }
        }
    }
    
    bool dfs(int u)
    {
        FF(i, 1, n+1) if(!vis[i] && g[u][i])
        {
            vis[i] = true;
            if(match[i] == 0 || dfs(match[i]))
            {
                match[i] = u;
                return true;
            }
        }
        return false;
    }
    
    bool max_match()
    {
        CLR(match, 0);
        FF(i, 1, n+1)
        {
            CLR(vis, 0);
            if(!dfs(i)) return false;
        }
        return true;
    }
    
    int main()
    {
        while(~scanf("%d%d", &n, &k))
        {
            CLR(degree, 0);CLR(g, 0);
            REP(i, n*k/2)
            {
                scanf("%d%d", &u, &v);
                g[u][v] = g[v][u] = 1;
                id[u][v] = id[v][u] = i+1;
                degree[u]++, degree[v]++;
            }
            Euler();
            if(max_match())
            {
                puts("YES");
                FF(i, 1, n+1) printf("%d
    ", id[match[i]][i]);
            }
            else puts("NO");
        }
        return 0;
    }
    


  • 相关阅读:
    11.个别程序题
    常见设计模式部分
    框架部分综合
    mybatis部分
    spring部分
    hibernate部分
    struts2部分
    10.java反射和类加载机制
    9.垃圾回收机制和JVM
    oracle部分
  • 原文地址:https://www.cnblogs.com/riskyer/p/3292322.html
Copyright © 2020-2023  润新知