思想
很明显,删掉节点4之后,剩下的1->2->3->5就构成一个环:
观察图像,我们发现,环上的点都有一条入边和出边,即度数为2.非环上的点只有一条入边,没有出边,度数为1.
所以我们只需要把度数为1的节点删除即可.
具体怎么操作呢?
观察样例我们发现,有出度的点必然会出现两次.因此我们只需要把作为出现一次的点删除即可:
还有一种情况就是下面这种:
]
像上图这种情况我们仍然是先把度为1的点加入队列当中(节点6),然后我们要去找与度为1的点(节点6)连接的那个点(节点4).
找到之后呢,我们把度为1的点(节点6)和连接的那个点(节点4)的边删掉,如下:
此时,节点4就成了新的度为1的节点.然后再把节点4加入到队列之中,重复上述步骤.最后变成下面这样:
这样就找到了环了
code
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int cnt[N], vis[N];
vector<int> edge[N];
queue<int>q;
int main()
{
int n, m; cin >> n >> m;
for (int i = 1; i <= m; i++)
{
int in, to; cin >> in >> to;
edge[in].push_back(to);
edge[to].push_back(in);
cnt[in]++;
cnt[to]++;
}
queue<int>que;
for (int i = 1; i <= n; i++)
{
if (cnt[i] == 1)
{
q.push(i);
vis[i] = 1;
}
}
while (!q.empty())
{
int from = q.front();
q.pop();
for (int to : edge[from])
{
if (--cnt[to] == 1)
{
q.push(to);
vis[to] = 1;
}
}
}
for (int i = n; i >= 1; i--)if (!vis[i])cout << i << " ";
return 0;
}