题目链接:https://codeforces.com/contest/1362/problem/D
题意:给你N个顶点M条边,要给每一个顶点写上一个topic,写这个主题时要根据与该顶点相邻的点的topic中取最小的那个未写过的topic,并且相邻的点不能用相同的topic,问是否存在这样一个序列使得满足题目要求。
思路:比较直接的想法就是从topic为1的优先填,因为前面的topic没填不可能去填后面的,它要基于相邻顶点的最小值的topic,因此我们可以贪心的从1到n去填,满足条件的是该顶点填上了topic的相邻点有i-1个(i为该顶点要填的topic),要注意的是如果两个顶点相邻且所需的topic相同不满足条件。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=5e5+10;
vector<int> e[maxn];
vector<int> t[maxn];
vector<int> ans;
int color[maxn],need[maxn];
int main()
{
int n,m,x,y,c;
cin>>n>>m;
for(int i=0;i<m;i++){
scanf("%d%d",&x,&y);
e[x].push_back(y);
e[y].push_back(x);
}
bool flag=true;
for(int i=1;i<=n;i++){
scanf("%d",&c);need[i]=c;
t[c].push_back(i);
}
for(int i=1;i<=n;i++){ //判断是否存在相邻点的topic相同
for(int j=0;j<e[i].size();j++){
if(need[i]==need[e[i][j]]){
cout<<-1; exit(0);
}
}
}
for(int i=1;i<=n;i++){
for(int j=0;j<t[i].size();j++){
int v=t[i][j];map<int,int> mp;c=0;
for(int k=0;k<e[v].size();k++){
int w=e[v][k];
if(color[w]!=0&&!mp[color[w]]){
mp[color[w]]=1;c++;
}
}
ans.push_back(v);
color[v]=i;
if(c!=i-1){
flag=false;break;
}
}
}
if(!flag) cout<<-1;
else for(int i=0;i<ans.size();i++) cout<<ans[i]<<" ";
return 0;
}