1. 程式人生 > >【推導】【貪心】XVII Open Cup named after E.V. Pankratiev Stage 4: Grand Prix of SPb, Sunday, Octorber 9, 2016 Problem H. Path or Coloring

【推導】【貪心】XVII Open Cup named after E.V. Pankratiev Stage 4: Grand Prix of SPb, Sunday, Octorber 9, 2016 Problem H. Path or Coloring

sin pat clas cst 發現 can -- cnblogs ret

題意:給你一張簡單無向圖(但可能不連通),再給你一個K,讓你求解任意一個問題:K染色或者輸出一條K長路徑。

直接貪心染色,對一個點染上其相鄰的點的顏色集合之中,未出現過的最小的顏色。

如果染成就染成了。如果到某個點,發現染不成,則倒著按照顏色從大到小回去,則一定恰好可以找出一條K長度的路徑。

#include<cstdio>
#include<cstring>
using namespace std;
int first[1005],next[20005],v[20005],e,co[1005];
void AddEdge(int U,int V){
	v[++e]=V;
	next[e]=first[U];
	first[U]=e;
}
int T,n,m,K;
bool cant[1005];
bool df2(int U){
	printf(" %d",U);
	if(co[U]==1){
		puts("");
		return 1;
	}
	for(int i=first[U];i;i=next[i]){
		if(co[v[i]]==co[U]-1){
			if(df2(v[i])){
				return 1;
			}
			break;
		}
	}
	return 0;
}
bool dfs(int U){
	int sta;
	for(int i=first[U];i;i=next[i]){
		if(co[v[i]]){
			cant[co[v[i]]]=1;
			if(co[v[i]]==K){
				sta=v[i];
			}
		}
	}
	for(int i=1;i<=K;++i){
		if(!cant[i]){
			co[U]=i;
			break;
		}
	}
	if(!co[U]){
		printf("path %d",U);
		df2(sta);
		return 1;
	}
	for(int i=first[U];i;i=next[i]){
		if(co[v[i]]){
			cant[co[v[i]]]=0;
		}
	}
	for(int i=first[U];i;i=next[i]){
		if(!co[v[i]]){
			if(dfs(v[i])){
				return 1;
			}
		}
	}
	return 0;
}
int main(){
//	freopen("h.in","r",stdin);
	int x,y;
	scanf("%d",&T);
	for(;T;--T){
		e=0;
		memset(first,0,sizeof(first));
		scanf("%d%d%d",&n,&m,&K);
		for(int i=1;i<=m;++i){
			scanf("%d%d",&x,&y);
			AddEdge(x,y);
			AddEdge(y,x);
		}
		memset(co,0,sizeof(co));
		memset(cant,0,sizeof(cant));
		bool sol_path=0;
		for(int i=1;i<=n;++i){
			if(!co[i]){
				if(dfs(i)){
					sol_path=1;
					break;
				}
			}
		}
		if(!sol_path){
			printf("coloring");
			for(int i=1;i<=n;++i){
				printf(" %d",co[i]);
			}
			puts("");
		}
	}
	return 0;
}

【推導】【貪心】XVII Open Cup named after E.V. Pankratiev Stage 4: Grand Prix of SPb, Sunday, Octorber 9, 2016 Problem H. Path or Coloring