邻接表写法
注意本题中为无向边,n虽然最大1e5,但是我们就要开2e5,不然过不去:
开2e5就可以过:
#include<bits/stdc++.h>
using namespace std;
int n;
const int N=1e5+10;
const int M=2*N;
int p[M];
int d[M],h[M],e[M],ne[M];
int cnt,idx;
void add(int a,int b)
{
e[idx]=b;
ne[idx]=h[a];
h[a]=idx++;
}
int main()
{
memset(h,-1,sizeof h); //初始化头节点
cin>>n;
for(int i=0;i<n;i++)
{
int a,b;cin>>a>>b;
add(a,b);add(b,a);
d[a]++,d[b]++; //无向边
}
queue<int> q;
for (int i = 1; i <= n; i++) //找到所有只连一条边的点
{
if (d[i] == 1)
q.push(i);
}
while(!q.empty())
{
int t=q.front();
q.pop();
for(int i=h[t];i!=-1;i=ne[i])
{
int j=e[i]; //x连的点y
d[j]--; //减去边
if(d[j]==1)q.push(j);
}
}
//环上的点至少有两条边,删去一条还有一条
for(int i=1;i<=n;i++)
{
if(d[i]>1)cout<<i<<" ";
}
return 0;
}#include<bits/stdc++.h>
using namespace std;
int n;
const int N=1e5+10;
const int M=2*N;
int p[M];
int d[M],h[M],e[M],ne[M];
int cnt,idx;
void add(int a,int b)
{
e[idx]=b;
ne[idx]=h[a];
h[a]=idx++;
}
int main()
{
memset(h,-1,sizeof h); //初始化头节点
cin>>n;
for(int i=0;i<n;i++)
{
int a,b;cin>>a>>b;
add(a,b);add(b,a);
d[a]++,d[b]++; //无向边
}
queue<int> q;
for (int i = 1; i <= n; i++) //找到所有只连一条边的点
{
if (d[i] == 1)
q.push(i);
}
while(!q.empty())
{
int t=q.front();
q.pop();
for(int i=h[t];i!=-1;i=ne[i])
{
int j=e[i]; //x连的点y
d[j]--; //减去边
if(d[j]==1)q.push(j);
}
}
//环上的点至少有两条边,删去一条还有一条
for(int i=1;i<=n;i++)
{
if(d[i]>1)cout<<i<<" ";
}
return 0;
}
结构体邻接表写法
#include <iostream>
#include <queue>
#include <stdio.h>
int p[200005];
int cnt;
struct edge {
int y;
int next;
};
int n;
struct edge e[200005];
int d[200005]; //记录某个点所连的边数 如果是有向图就记录点的入度
void add(int x,int y) //邻接表存图
{
e[++cnt].next = p[x];
e[cnt].y = y;
p[x] = cnt;
}
int main()
{
scanf("%d",&n);
int a, b;
for (int i = 0; i < n; i++)
scanf("%d%d", &a, &b), add(a, b), add(b, a), d[a]++,d[b]++; //无向图
std::queue<int> q;
for (int i = 1; i <= n; i++) //找到所有只连一条边的点
{
if (d[i] == 1)
q.push(i);
}
while (q.size())
{
int x = q.front();
q.pop();
for (int i = p[x]; i; i = e[i].next)
{
int j = e[i].y; //x连的点y
d[j]--; //x-y这条边删掉
if (d[j] == 1) //如果还有一条边,继续删除
q.push(j);
}
}
for (int i = 1; i <= n; i++) //如果还有点连的边数大于1,成环
if(d[i] > 1)
printf("%d ",i);
return 0;
}