• Codeforces Gym 100431A Achromatic Number 欧拉回路


    原题链接:http://codeforces.com/gym/100431/attachments/download/2421/20092010-winter-petrozavodsk-camp-andrew-stankevich-contest-37-asc-37-en.pdf

    题意

    给你一个n,让你构造一个环,使得相邻的节点的颜色不一样,问最多能使用多少颜色,并且输出染色方案。

    题解

    首先,我们来考察对于k个颜色,我们至少需要多少节点。每个点可以连接两个点,将边考虑为有向边,如果我们不浪费任何一条边,对于一个颜色,我们将它连到其余的一半的颜色,将另外一半的颜色连接到他,由于可能除不尽,所以要向上取整。这样,我们得到了一个简单的公式,对于偶数的颜色k,我们需要k*k/2的点,对于奇数的颜色k,我们需要k*(k-1)/2的点。

    现在反过来思考,对于给定的节点数,我们至少需要多少颜色。如果刚刚够用,自然最好,如若不然,就寻找一个合适的k,然后采取在多于的节点随便染色的策略。但事实并非如此,因为题意要求是个环,那么我们如若在最后补颜色,那么就会拆开最后一条边,所以,如果给的n只比合适值多1,那么颜色数就要减一,这就是为什么4个点的答案是2而3个点的答案是3。

    接下来,我们来考虑如何构造解。对于我们已经构建好的有向图,本质上是要遍历所有的边。那么只需要在最初弄好的颜色的有向图上跑一发欧拉回路。然后我们需要填充多于的节点,为了避免出现拆开唯一的颜色边,所以应当将一个重复的边拆开,再在里面插点。插点时需要满足题意的条件。

    此题坑非常多,需要十分细致,最好手算一下前10的答案,然后比对一下输出。

    代码

    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<cstdio>
    #include<vector>
    #define MAX_N 1234
    using namespace std;
    
    int gao[MAX_N];
    int k;
    struct edge
    {
        bool vis;
        int to;
        edge(int t)
                :vis(0),to(t){}
        edge(){}
    };
    
    vector<edge> G[MAX_N];
    int tot=0,road[MAX_N];
    bool flag=false;
    int n;
    
    int st[MAX_N],all=0;
    
    void dfs(int u) {
        //cout<<u<<endl;
        int i = gao[u];
        while (i < G[u].size() && G[u][i].vis)i++;
        if (i == G[u].size())return;
        gao[u] = i + 1;
        G[u][i].vis = 1;
        st[all++] = G[u][i].to;
        dfs(G[u][i].to);
    }
    
    bool check(int u) {
        //cout<<G[u][0].vis<<endl;
        if (gao[u] == G[u].size())return false;
        return true;
    }
    
    void Fluery(int s) {
        st[all++] = s;
        while (all) {
            int now = st[all - 1];
            if (check(now))dfs(now);
            else {
                //cout<<rHash(now)<<endl;
                road[tot++] = now;
                all--;
            }
        }
    }
    
    bool vis[MAX_N][MAX_N];
    int newRoad[MAX_N];
    
    int main() {
        freopen("achromatic.in","r",stdin);
        freopen("achromatic.out","w",stdout);
        scanf("%d", &n);
        for (k = 0; ; k++) {
            int t;
            if (k & 1)t = k * (k - 1) / 2;
            else t = k * k / 2;
            if (t > n)break;
        }
        k--;
        if ((k & 1) && n == (k * (k - 1)) / 2 + 1)k--;
        printf("%d
    ", k);
        for (int i = 0; i < k; i++)
            for (int j = 1; j <= k / 2; j++) {
                int u = i;
                int v = (i + j) % k;
                G[u].push_back(edge(v));
            }
        Fluery(0);
        int pos = 0;
        for (int i = 0; i < tot - 1; i++) {
            int u = i, v = (i + 1) % (tot - 1);
            if (vis[u][v]) {
                pos = u;
                break;
            }
            vis[u][v] = vis[v][u] = 1;
        }
        int nt = 0;
        for (int i = pos + 1; i < tot - 1; i++)
            newRoad[nt++] = road[i];
        for (int i = 0; i <= pos; i++)newRoad[nt++] = road[i];
        for (int i = 0; i < tot - 1; i++)
            printf("%d ", newRoad[i] + 1);
        if (n == tot - 1) { return 0; }
        if (n - (tot - 1) == 1) {
            int j = 1;
            while (j == newRoad[tot - 2] + 1 || j == newRoad[0] + 1) {
                j++;
                if (j == k + 1)j = 1;
            }
            printf("%d
    ", j);
            return 0;
        }
        printf("%d ", newRoad[0] + 1);
        int p = newRoad[0] + 1;
        for (int i = tot; i < n; i++) {
            int j = 1;
            while (j == p || (i == n - 1 && j == newRoad[0] + 1)) {
                j++;
                if (j == k + 1)j = 1;
            }
            printf("%d ", j);
            p = j;
        }
        printf("
    ");
        return 0;
    }
  • 相关阅读:
    做一个项目,平时都用到哪些工具提高效率(上)
    做项目时,如何做比较美观大方的数据输入窗体
    做一个项目,平时都用到哪些工具提高效率(中)
    类型的初试化器的调用时机
    数据加密小工具
    ASP.NET 开发知识小结
    做一个项目,平时都用到哪些工具提高效率(下)
    两道面试题目 关于new和override的
    js技巧,js找到html中的注释,js让客户端另存一段文本
    在适当的场合使用FlagsAttribute修饰枚举
  • 原文地址:https://www.cnblogs.com/HarryGuo2012/p/4737555.html
Copyright © 2020-2023  润新知