码迷,mamicode.com
首页 > 其他好文 > 详细

UVa 193 图着色

时间:2015-03-09 12:57:58      阅读:155      评论:0      收藏:0      [点我收藏+]

标签:uva   回溯   暴力求解      递归   

题意:给一个图,可以染白色和黑色,但是染黑色的结点不能相邻。求最多的黑色结点个数,和一种可能的黑色结点序列。

思路:这个用回溯法还是很容易想到怎么写的。dfs每一个位置,知道所有位置dfs完。对每个位置都尝试黑色和白色。如果染黑色,那么就需要把和它相邻的结点染成白色,因为他们必须是白色,如果发现有相邻结点已经是黑色,则当前结点不能是黑色;而因为dfs后需要对辅助的全局变量进行恢复,所以这里在将相邻结点染成白色前先判断它是不是已经是白色了,因为如果它已经是白色在恢复的时候就不需要再恢复了,否则需要把它恢复成未染色的状态。  程序实现,我用的是color数组,0表示未染色,1表示黑色,2表示白色。dfs只需要对未染色的结点进行详细考虑,其中在染成黑色时用一个数组保存了相邻的、本来就是白色结点的结点编号;已染色的结点只要简单地dfs下一位置即可。

注意:这里结点的编号是从1到n,数组要开够,而且循环的索引及范围要注意下。

            第二个,就是要注意全局变量的初始化。这里特别要注意的是g数组的初始化,之前以为反正是要赋值的,就没初始化。。。之后发现边数为0的话,那g数组就是上个数据的了。。其实,就算边数不为0,是其他的数,g数组不初始化的话,上一数据的边的关系还是会残留在这组数据的。。。

            第三个,就是输出的时候,给出一种可能的序列就可以了。最后一个数之后没有空格,直接回车。否则会 PE 错误。(终于遇到一次PE了啊,之前记得格式错很多都提示WA的,所以这题第一次WA的时候,怀疑是不是输出的原因,结果并不是。。。)

给一些测试数据:

input

5
6 8
1 2
1 3
2 4
2 5
3 4
3 6
4 6
5 6


2 1
1 2


3 2
1 2
1 3


5 0


8 4
1 2
3 4
5 6
6 8

output

3
1 4 5 
1

2
2 3 
5
1 2 3 4 5 
5
1 3 5 7 8 

Code:

#include<stdio.h>
#include<string.h>

void dfs(int cur,int n);

int g[102][102];
int color[102];
int bestclr[102];
int bestblk;

int main()
{
  //freopen("193.in","r",stdin);
  //freopen("193.out","w",stdout);
    
  int m;
  scanf("%d",&m);
  while(m-->0)
  {
    bestblk=0;
    memset(color,0,sizeof(color));
    memset(g,0,sizeof(g));
    int n,k;
    scanf("%d%d",&n,&k);
    int a,b;
    for(int i=0;i<k;++i)
    {
      scanf("%d%d",&a,&b);
      g[a][b]=1;
      g[b][a]=1;
    }
    dfs(1,n);
    printf("%d\n",bestblk);
    //for(int i=0;i<=n;++i) if(bestclr[i]==1) printf("%d ",i);
    //printf("\n");
    int num=0;
    int i=1;
    for(;i<=n;++i)
    {
      if(num==bestblk-1) break;
      if(bestclr[i]==1) { printf("%d ",i); num++;}
    }
    for(;i<=n;++i)
      if(bestclr[i]==1) { printf("%d\n",i); break;}
  }
  return 0;
}

void dfs(int cur,int n)
{
  if(cur==n+1)
  {
    int num=0;
    for(int i=1;i<=n;++i) if(color[i]==1) num++;
    if(num>bestblk) { bestblk=num; memcpy(bestclr,color,sizeof(color));}
    return ;          
  }
    if(color[cur]==0)
    {
      color[cur]=1;//黑色
      int ok=1;
      int tempnd[n];
      int cnt=0;
      for(int j=1;j<=n;++j)
        if(g[cur][j])      
        {
          if(color[j]==1) { ok=0; break;}     
          else if(color[j]==0) { color[j]=2;}
          else tempnd[cnt++]=j;//保留原来就是白色的结点编号          
        }
      if(ok) dfs(cur+1,n);
      //恢复
      for(int j=1;j<=n;++j)
        if(g[cur][j]&&color[j]==2)
        {
          int flag=1;
          for(int i=0;i<cnt;++i)
            if(tempnd[i]==j) { flag=0; break;}
          if(flag) color[j]=0;
        }
      color[cur]=0;
      dfs(cur+1,n);
    }
    else
      dfs(cur+1,n);
}

论文中了,非常happy~

UVa 193 图着色

标签:uva   回溯   暴力求解      递归   

原文地址:http://blog.csdn.net/buxizhizhou530/article/details/44152219

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!