BZOJ4878: [Lydsy2017年5月月赛]挑战NP-Hard

来源:互联网 发布:golang microservice 编辑:程序博客网 时间:2024/06/05 14:33

题目地址http://www.lydsy.com/JudgeOnline/problem.php?id=4878

Description

天才大学生quailty热衷于解决NP-Hard问题,你如果AC 了这道题,就可以成为他真正的粉丝。图染色问题:给定
无向图G和一个正整数k。对于图中的每个点,选择一个在[1,k]之间的整数作为其颜色。你需要保证对于每条边,
其两端点的颜色均不相同。简单k路径问题:给定无向图G和一个正整数k。请找到一条经过了恰好k条边的简单路径
。即,你需要找到一个长度为k+1的序列v_1,v_2,...,v_{k+1},满足1<=v_i<=n,且任意两个v均不相同,同时v_i
与v_{i+1}之间存在一条边。现在给定无向图G和一个正整数k,quailty知道你没有他的水平,所以你只需解决上面
的任意一个问题就可以成为他的粉丝。

Input

第一行包含一个正整数T(1<=T<=1000),表示测试数据的组数。
对于每组数据,第一行包含三个正整数n,m,k(1<=n<=1000,1<=m<=10000,1<=k<=n),分别表示图的点数与边数。
接下来m行,每行两个正整数a,b(1<=a,b<=n),表示a到b之间存在一条无向边。
输入数据保证不存在重边与自环,且总边数不超过100000。

Output

对于每组数据:
若选择了图染色问题,请输出“color”,然后输出n个在1到k之间的正整数,分别表示每个点的颜色。
若选择了简单路径问题,请输出“path”,然后输出k+1个在1到n之间的正整数,分别表示路径上每个点的编号。
若有多组可行解,输出任意一组。

Sample Input

2
4 5 2
1 2
2 3
3 4
4 1
1 3
3 3 3
1 2
2 3
3 1

Sample Output

path 3 2 1
color 1 2 3
/*考虑尝试对图进行贪心染色,col[x]=mex(col[y]),其中x与y有边,且y已被染过色若max(col[i])<=k,那么k染色问题就解决了否则随便选一个颜色是k+1的点,按照颜色递减走,一定可以走出一条边数为k的简单路径时间复杂度O(n+m)*/#include<cstdio>const int N=1010,M=20010;int Case,n,m,K,i,j,x,y,g[N],v[M],nxt[M],ed,vis[N],col[N],pos;inline void add(int x,int y){v[++ed]=y;nxt[ed]=g[x];g[x]=ed;}void dfs(int x){  pos++;  for(int i=g[x];i;i=nxt[i])if(col[v[i]])vis[col[v[i]]]=pos;  for(int i=1;;i++)if(vis[i]<pos){    col[x]=i;    break;  }  for(int i=g[x];i;i=nxt[i])if(!col[v[i]])dfs(v[i]);}void solve(){  scanf("%d%d%d",&n,&m,&K);  for(ed=0,i=1;i<=n;i++)g[i]=col[i]=0;  while(m--)scanf("%d%d",&x,&y),add(x,y),add(y,x);  for(i=1;i<=n;i++)if(!col[i])dfs(i);  bool flag=0;  for(i=1;i<=n;i++)if(col[i]>K){flag=1;break;}  if(!flag){    printf("color");    for(i=1;i<=n;i++)printf(" %d",col[i]);    return;  }  for(i=1;i<=n;i++)if(col[i]==K+1){x=i;break;}  printf("path");  for(i=1;i<=K+1;i++){    printf(" %d",x);    for(j=g[x];j;j=nxt[j])if(col[v[j]]==col[x]-1){      x=v[j];      break;    }  }}int main(){  scanf("%d",&Case);  while(Case--){    solve();    puts("");  }  return 0;}


阅读全文
1 0
原创粉丝点击