拿到这道题后,知道tarjan算法的应该第一反应就是用tarjan缩点来求。观察一下数据范围,其实我们可以将裸的缩点模板打上去。问题可能集中在第二问,我们只需记录下染色的数组,在第二问时从小到大遍历如果当前点染的是最大的那个颜色,就输出来即可。
(代码下附题目背景人物 车万永不过气)
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<stack>
using namespace std;
const int maxn=5010;
const int maxm=50010;
int head[maxn],nnext[maxm*2],to[maxm*2];
int dfn[maxn],low[maxn],color[maxn],cnt[maxn];
bool instack[maxn],b[maxn];
int n,m,tot,id,num,ink,v;
stack<int> q;
void add(int x,int y)
{
tot++;
nnext[tot]=head[x];
head[x]=tot;
to[tot]=y;
}
void tarjan(int x)
{
dfn[x]=low[x]=++id;
b[x]=instack[x]=true;
q.push(x);
for(int i=head[x];i;i=nnext[i])
{
int y=to[i];
if(!b[y])
{
tarjan(y);
low[x]=min(low[x],low[y]);
}
else if(instack[y])
{
low[x]=min(low[x],low[y]);
}
}
if(dfn[x]==low[x])
{
ink++;
do
{
v=q.top();
q.pop();
instack[v]=false;
color[v]=ink;
cnt[ink]++;
}while(v!=x);
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int x,y,k;
scanf("%d%d%d",&x,&y,&k);
if(k==2) add(y,x);
add(x,y);
}
for(int i=1;i<=n;i++)
{
if(!dfn[i]) tarjan(i);
}
int ans=-100,qwq;
for(int i=1;i<=ink;i++)
{
if(ans<cnt[i])
{
ans=cnt[i];
qwq=i;
}
}
printf("%d\n",ans);
for(int i=1;i<=n;i++)
{
if(color[i]==qwq)
{
cout<<i<<' ';
}
}
return 0;
}