题目概述
在一棵树中新增一条边,使得这个图产生一个环,求在环上的点。
思路:拓补排序
对于这道题显然不能生搬硬套拓补排序的模板。
这道题中的图是一个无向图,而拓补排序却是处理有向图的一种思想。
不难想到可以将无向图转化为有向图,即将对于每条无向边变换为双向建边,就好处理了。
在这种情况下,很显然当一个点的入度大于或等于 \(2\) 时,即有不止一条边连向这个点时,该点就在环上。
我们可以建一个布尔类型 \(vis\) 数组来标记这个点的入度是否等于 \(1\),那么这个点就不在环上,那么没有被标记的点就是我们要求的答案了。
Code
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+1;
int n;
int in[N];
vector<int>e[N];
bool vis[N];//标记入度是否为1,即该点是否在环上
void topo()//拓补排序
{
queue<int>q;
for(int i=1;i<=n;i++)
if(in[i]==1)//标记入度为1的点
{
q.push(i);
vis[i]=true;
}
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=0;i<e[u].size();i++)
{
int v=e[u][i];
in[v]--;
if(in[v]==1)//标记入度为1的点
{
q.push(v);
vis[v]=true;
}
}
}
}
void print()//输出未标记的点
{
for(int i=1;i<=n;i++)
if(!vis[i])cout<<i<<' ';
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
int u,v;
cin>>u>>v;
e[u].push_back(v);
e[v].push_back(u);//双向建边
in[u]++;
in[v]++;//两点的入度都增加
}
topo();
print();
return 0;
}
标签:环上,int,题解,入度,蓝桥,2017,排序,拓补
From: https://www.cnblogs.com/FHenryh/p/solution-luogu-P8655.html