UVA1613

题目大意:
给一个无向图,n个顶点(n为奇数),m条边,求的一个最小的奇数k,使得k满足:
①:k>=顶点的最大度数
②:1-k种颜色可以涂满整个图,使得图当中任意两个相连的顶点的颜色不同。
思路:
在输入的时候记录下每个顶点的度数,求的最大度数maxDegree;
使用bfs求出最小的使用的颜色数目tmp;
结果即为ans = max(tmp , maxDegree); printf(“%d\n” ans|1);
最后只需要bfs进行染色就可以了。

优化 :
当度数最大顶点的度数为偶数的时候,需要最多的颜色 k= 顶点度数+1(顶点本身), 最大需要颜色数为 与其他所有都相连 k+1 <= k|1
当度数最大顶点的度数为奇数的时候,需要最多的颜色 k= 顶点度数+1(顶点本身),颜色各不相同,此时为完全图,得到顶点数为偶数,与题目描述不符。
所以ans = maxDegree|1;

代码如下:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<queue>
#include<cstring>
using namespace std;

int degree[10055]; //记录每一个顶点的度数 
int color[10055];  //记录每一个顶点的颜色 
int maxDegree; //记录最大度数 


/************
图论常用: 链式向前星 -->邻接表记录 图结构 
***********/
int head[10055];  
struct e{
    int v , nxt;
}edge[200505]; 
int Ecnt;

void addEdge(int u , int v){
    edge[Ecnt].v = v;
    edge[Ecnt].nxt = head[u];
    head[u]=Ecnt++;
}


int colorUsed[10005];//该颜色是否被相邻的顶点用过 
int used[10055]; //该顶点是否 进入过队列 


void BFS(int src){
    queue<int> q;
    q.push(src);

    memset(used , 0 ,sizeof(used));
    used[src] =1;

    while(!q.empty()){
        int index = q.front();
        q.pop();    
        memset(colorUsed , 0 , sizeof(colorUsed));

        for(int i=head[index] ; i!=-1 ; i=edge[i].nxt){
            int v = edge[i].v;

            if(color[v]!=-1) {  //记录下 周围顶点已经 用过的颜色          
                colorUsed[color[v]]=1;          
            }else if(used[v] == 0){ //若 周围顶点未进入过 队列 则入队 
                    used[v] = 1;
                    q.push(v);
            }
        }

        int j;
        for(j=1 ;j<=maxDegree ; ++j){//用最小的 未被用过颜色 来涂当前顶点 
            if(!colorUsed[j]){
                color[index] = j;
                break;
            }
        }
    }
}

//初始化 
void Init(){
    Ecnt = 0 ;
    maxDegree = 0;
    memset(head , -1 , sizeof(head));
    memset(degree , 0 ,sizeof(degree)); 
    memset(color , -1 ,sizeof(color));
}


int main(){
    bool first = true;
    int n, m;
    while(scanf("%d %d",&n , &m)!=EOF){ 

        Init();
        if (first)
           first = false;
        else
             printf("\n");

        int u ,v;
        for(int i=0 ; i<m ; ++i){
            scanf("%d %d",&u,&v);
            if(u == v) continue;
            addEdge(u,v);
            addEdge(v,u);
            degree[u]++;
            degree[v]++;
        }   
        for(int i=1 ;i<=n ; ++i){
            if(maxDegree < degree[i]){
                maxDegree = degree[i];
            }
        }

        if(maxDegree%2 == 0) maxDegree++;

        BFS(1);

        printf("%d\n",maxDegree);

        for(int i=1 ;i<=n ;++i)
            printf("%d\n",color[i]);        
    }

    return 0;
}

链式向前星:http://blog.csdn.net/acdreamers/article/details/16902023

错点:
一开始超时,发现错误发生在:判断顶点若未被涂色就入队, 可能该点未被涂色但是已经在队列当中了,造成了多次入队现象 ,造成超时。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值