一个合适的顶点着色是指用各种颜色标记图中各个顶点,使得每条边的两个端点的颜色都不相同。
如果一种合适的顶点着色方案使用了一共 k 种不同的颜色,则称其为合适的 k 着色(k-coloring)。
现在,你需要判断给定的着色方案是否是合适的 k 着色方案。
输入格式
第一行包含两个整数 N 和 M,分别表示点和边的数量。
接下来 M 行,每行包含两个整数 a,b,表示点 a 和点 b 之间存在一条边。
所有点的编号从 0 到 N−1。
再一行包含一个整数 K,表示你需要判断的着色方案。
接下来 K 行,每行包含 N 个颜色,其中第 i 个颜色表示第 i 个点的颜色。
颜色用非负整数表示,不超过 int 范围。
输出格式
对于每种着色方案,如果是一种合适的 k 着色方案,则输出一行 k-coloring。
如果不是合适的着色方案,则输出一行 No。
数据范围
1≤N,M≤104,
1≤K≤100
输入样例:
10 11
8 7
6 8
4 5
8 4
8 1
1 2
1 4
9 8
9 1
1 0
2 4
4
0 1 0 1 4 1 0 1 3 0
0 1 0 1 4 1 0 1 0 0
8 1 0 1 4 1 0 5 3 0
1 2 3 4 5 6 7 8 8 9
输出样例:
4-coloring
No
6-coloring
No
这道题一开始用了DFS做,超时
#include<bits/stdc++.h>
using namespace std;
struct node
{
int color;
vector<int> val;
}a[10010];
int flag;
int vis[10010];
void dfs(int x)
{
if(flag==0)
return ;
for(int each:a[x].val)
{
if(vis[each]==0)
{
if(a[each].color == a[x].color)
{
flag=0;
return ;
}vis[x]=1;
dfs(each);
vis[x]=0;
}
}
}
int main()
{
ios::sync_with_stdio(false);
int n,m;
cin >> n>>m;
for(int i=1;i<=m;i++)
{
int x,y;
cin >> x >>y;
a[x].val.push_back(y);
a[y].val.push_back(x);
}
int t;
cin >>t;
while(t--)
{
set<int> s;
flag=1;
memset(vis,0,sizeof(vis));
for(int i=0;i<n;i++)
{
int color;
cin >> color;
a[i].color = color;
s.insert(color);
}
vis[0]=1;
dfs(0);
if(flag==1)
cout <<s.size()<<"-coloring"<<endl;
else
cout <<"No"<<endl;
}
return 0;
}
改用了一个BFS,过了
#include<bits/stdc++.h>
using namespace std;
struct node
{
int color;
vector<int> val;
}a[10010];
int flag;
int vis[10010];
void bfs()
{
queue<int> q;
q.push(0);
while(!q.empty())
{
int now = q.front();
q.pop();
if(vis[now])
continue;
vis[now] = 1;
for(int each:a[now].val)
{
if(vis[each]==0)
{
if(a[each].color == a[now].color)
{
flag=0;
return ;
}
q.push(each);
}
}
}
}
int main()
{
ios::sync_with_stdio(false);
int n,m;
cin >> n>>m;
for(int i=1;i<=m;i++)
{
int x,y;
cin >> x >>y;
a[x].val.push_back(y);
a[y].val.push_back(x);
}
int t;
cin >>t;
while(t--)
{
set<int> s;
flag=1;
memset(vis,0,sizeof(vis));
for(int i=0;i<n;i++)
{
int color;
cin >> color;
a[i].color = color;
s.insert(color);
}
bfs();
if(flag==1)
cout <<s.size()<<"-coloring"<<endl;
else
cout <<"No"<<endl;
}
return 0;
}
其实这道题还有更简单的方法,就是用每条边的两个点判断颜色是否相等即可。
#include <bits/stdc++.h>
using namespace std;
int color[10100],a[10100],b[10100];
int n,m,t;
int main()
{
ios::sync_with_stdio(false);
cin >> n >>m;
for(int i=1;i<=m;i++)
{
cin >> a[i]>>b[i];
}
cin >> t;
while(t--)
{
unordered_set<int> s;
for(int i=0;i<n;i++)
{
cin >>color[i];
s.insert(color[i]);
}
int i;
for( i=1;i<=m;i++)
{
if(color[a[i]]==color[b[i]])
{
cout <<"No"<<endl;
break;
}
}
if(i>m)
cout <<s.size()<<"-coloring"<<endl;
}
return 0;
}