基环树
简单无向图有n个点n-1条边,那么它们会连成一条直线
n个点n条边,相对多一条边,有且仅有一个环
可以利用拓扑排序找这个环
例题:F - Well-defined Path Queries on a Namori
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 2e5 + 10,MAXM = 2e5 + 10;
int n,q;
struct edge{
int v;
edge* nex;
}ed[MAXM * 2];
edge* head[MAXN];
int ptop = 0;
void add(int u,int v)
{
ed[ptop].v = v;
ed[ptop].nex = head[u];
head[u] = &ed[ptop];
ptop++;
}
int du[MAXN];
bool unable[MAXN];
int co = 1;//颜色
int color[MAXN];
void tp()//拓扑排序,找环
{
queue<int> qu;
for(int i = 1;i <= n;i++)
if(du[i] == 1)
qu.push(i);
while(!qu.empty())
{
int u = qu.front();qu.pop();
unable[u] = 1;
edge* p = head[u];
while(p != NULL)
{
int v = p -> v;
du[v]--;
if(du[v] == 1)
qu.push(v);
p = p -> nex;
}
}
}
bool use[MAXN];
void dfs(int c,int p)//染色
{
if(use[p] || !unable[p])
return;
use[p] = 1;
color[p] = c;
edge* pp = head[p];
while(pp != NULL)
{
int v = pp -> v;
dfs(c,v);
pp = pp -> nex;
}
}
int main()
{
cin >> n;
for(int i = 1;i <= n;i++)
{
int u,v;cin >> u >> v;
du[u]++,du[v]++;
add(u,v);
add(v,u);
}
tp();
for(int i = 1;i <= n;i++)
{
if(!unable[i])
{
color[i] = co;
edge* p = head[i];
while(p != NULL)
{
int v = p -> v;
dfs(co,v);
p = p -> nex;
}
co++;
}
}
cin >> q;
while(q--)
{
int u,v;cin >> u >> v;
if(color[u] == color[v])
cout << "Yes" << endl;
else
cout << "No" << endl;
}
}
标签:pp,int,基环树,MAXN,nex,du,ptop
From: https://www.cnblogs.com/xxcdsg/p/17544285.html