题目描述
天才大学生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知道你没有他的水平,所以你只需解决上面
的任意一个问题就可以成为他的粉丝。
好题
我们对图进行如下染色:一个点的颜色是相邻节点颜色的mex(没染的颜色记作0)。
如果我们最后这样使得染出的最大颜色不超过k,就解决了第一个问题。
否则,我们找到一个颜色为k+1的, 一定有一个颜色为k的与它相邻,同样有k-1……这样找到了一条长度为k+1的简单路径,就解决了第二个问题。
#include<cstdio>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fd(i,a,b) for(i=a;i>=b;i--)
using namespace std;
typedef long long ll;
const int maxn=10000+10,maxm=100000+10;
int ans[maxn],d[maxn],now[maxn],a[maxn],b[maxn],c[maxn];
int co[maxn];
int h[maxn],go[maxm*2],nex[maxm*2];
bool bz[maxn];
int i,j,k,w,l,t,n,m,K,tot,ca,T,mx;
bool czy;
int read(){
int x=0,f=1;
char ch=getchar();
while (ch<'0'||ch>'9'){
if (ch=='-') f=-1;
ch=getchar();
}
while (ch>='0'&&ch<='9'){
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
int random(int x){
int t=rand()%10000;
t=t*10000+rand()%10000;
return t%x;
}
void add(int x,int y){
d[y]++;
go[++tot]=y;
nex[tot]=h[x];
h[x]=tot;
}
int main(){
T=read();
while (T--){
n=read();m=read();K=read();
//K++;
tot=0;
fo(i,1,n) d[i]=h[i]=0;
fo(i,1,m){
j=read();k=read();
add(j,k);add(k,j);
}
fo(i,1,n) co[i]=0;
mx=0;
fo(i,1,n){
t=h[i];
while (t){
bz[co[go[t]]]=1;
t=nex[t];
}
bz[0]=1;
co[i]=0;
while (bz[co[i]]) co[i]++;
mx=max(mx,co[i]);
t=h[i];
while (t){
bz[co[go[t]]]=0;
t=nex[t];
}
}
if (mx<=K){
printf("color ");
fo(i,1,n) printf("%d ",co[i]);
printf("\n");
}
else{
printf("path ");
fo(i,1,n)
if (co[i]==K+1) break;
j=i;
printf("%d ",j);
fd(i,K,1){
t=h[j];
while (t){
if (co[go[t]]==i) break;
t=nex[t];
}
j=go[t];
printf("%d ",j);
}
printf("\n");
}
}
}