UVA 1613 K-Graph Oddity K度图着色 (构造)

题意:在一个n个点的无向连通图中,n是奇数,k是使得所有点的度数不超过k的最小奇数,询问一种染色方案,使得相邻点的颜色不同。

题解:一个点和周围的点的颜色数加起来最大为它的度数+1;如果最大度数是偶数,那么k种颜色一定够了。如果最大度数是奇数,而且n是奇数,那么k种颜色也一定是足够的。 可以反证,最大度数的点是u,deg[u]是奇数,而且和u相邻的点颜色各不相同,那么与u的一个相邻点v,至少和deg[u]个颜色不同的点相邻,这样构造出来连通图点数一定是偶数,和n是奇数是矛盾的,所以不会出现颜色数为deg[u]+1的情况。

所以只要染色就好了。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e4;
const int maxm = 2e5+5;

int head[maxn],to[maxm],nxt[maxm],col[maxn],ecnt,deg[maxn];
int vis[maxn];

void addEdge(int u,int v)
{
    deg[u]++;
    to[ecnt] = v;
    nxt[ecnt] = head[u];
    head[u] = ecnt++;
}
int k;

void dfs(int u)
{
    for(int i = head[u]; ~i; i= nxt[i]){
        vis[col[to[i]]] = u;
    }

    for(int i = 1; i <= k; i++) if(vis[i] != u) { col[u] = i; break; }

    for(int i = head[u]; ~i; i= nxt[i]){
        if(col[to[i]]) continue;
        dfs(to[i]);
    }
}


int main()
{
    //freopen("in.txt","r",stdin);
    int n,m;
    while(~scanf("%d",&n)){
        scanf("%d",&m);
        memset(head+1,-1,sizeof(int)*n);
        memset(deg+1,0,sizeof(int)*n);
        memset(col+1,0,sizeof(int)*n);
        ecnt = 0;
        while(m--){
            int u,v;
            scanf("%d %d",&u,&v);
            addEdge(u,v); addEdge(v,u);
        }

        k = (*max_element(deg+1,deg+1+n))|1;
        memset(vis+1,0,sizeof(int)*k);

        dfs(1);
        printf("%d
",k);
        for(int i = 1; i <= n; i++) printf("%d
",col[i]);
        putchar('
');
    }
    return 0;
}
原文地址:https://www.cnblogs.com/jerryRey/p/4702323.html