一、题目
CF263D
题目大意:给定一个 n 个点,m 条边的无向图,保证图中每个节点的度数大于等于 k,求图中一条长度大于 k 的简单的环,输出长度和路径包含的点。
二、思路
因为是要找环,所以可以用dfs来做,图是连通图,随便从哪个点开始dfs都行,每次dfs的时候,将当前点到起始点的距离存下来,然后枚举与这个点相连的每一条边,当枚举到的边在之前已经遍历过,那就代表可以形成一个环,这个环的大小就是当前的点到起始点的距离减去枚举到的点到起始点的距离+1。
输出路径的话,每次dfs的时候将这个点加入vector里,做完当前的dfs的时候记得把这个点从vector里面删掉,这样vector里存的就是从起始点到当前点的路径,因为环所经过的点也在这条路径上,所以可以直接输出
三、代码
#include<bits/stdc++.h>
using namespace std;
const int N = 200020;
int e[N], ne[N], h[N], dist[N];
int idx;
bool st[N], flag, stt[N];
int n, m, k;
vector<int> ans;
void add(int a, int b){ //用邻接表来存边
e[idx] = b;
ne[idx] = h[a];
h[a] = idx ++;
}
void dfs(int x, int deep){ //deep表示当前点到起始点的距离
if(st[x]) return;
st[x] = true;
ans.push_back(x); //将当前点压入路径数组ans
dist[x] = deep;
for(int i = h[x]; i != -1 && !flag; i = ne[i]){
int j = e[i];
if(st[j] && deep - dist[j] >= k){ //如果st[j]=true表示找到环,deep-dist[j]表示这个环的长度-1的值,因为该点到j点的距离还没算上
int pos = 0;
while(ans[pos] != j) pos ++;
cout << deep - pos + 1 << endl; //输出环的长度
for(int k = pos; k <= deep; k ++){
cout << ans[k] << " "; //输出路径
}
cout << endl;
flag = true;
}
else dfs(j, deep + 1);
}
//stt[x] = true;
ans.pop_back();
}
int main(){
cin >> n >> m >> k;
memset(h, -1, sizeof h);
int u, v;
for(int i = 1; i <= m; i ++){
cin >> u >> v;
add(u, v);
add(v, u);
}
dfs(1, 0);
return 0;
}