题意
给你一个无向图,n个点n条边,保证图连通,并且有且只有有一个环,求出每个点距离环的距离
分析:第一次写这样的问题,之前听说过环缩点但是不知道具体算法是什么样子的。
大体算法是两次bfs,第一次找出属于环的点,第二次是将环向外bfs。
第一次bfs:将所有度为1的点加入队列中(因为度为1的点必定不是环里的点)进行bfs,如果遇到度>=3的点,先将这个点的度剪去1,直到这个点的度为2的时候才将其加入队列,并且标记vis 。
因为如果的环上的点,度不可能被减为2。环内部的点度虽然为2但是不会被访问到。
#include <iostream> #include <cstdio> #include <cstring> #include <queue> #include <algorithm> using namespace std; #define MAX_N 3005 #define MAX_M 10007 struct ed { int to; int next; }edge[MAX_M]; int n; int stu[MAX_N]; int col = 0; int ednum[MAX_N]; bool vis[MAX_N]; void addedge(int u , int v) { edge[col].to = v; edge[col].next = stu[u]; stu[u] = col++; } void bfs(){ queue<int> que; for (int i = 1; i <= n ; ++i) { if(ednum[i] == 1){ que.push(i); vis[i] = true; } } while(!que.empty()) { int tem = que.front(); que.pop(); for (int i = stu[tem]; i !=-1 ; i = edge[i].next) { if(vis[edge[i].to]) continue; if(ednum[edge[i].to]==2) { que.push(edge[i].to); vis[edge[i].to] = true; } else ednum[edge[i].to]--; } } } int ans[MAX_N]; void bfs2() { queue<int> que; for (int i = 1; i <= n ; ++i) { if(!vis[i]) que.push(i); } while(!que.empty()) { int tem = que.front(); que.pop(); for (int i = stu[tem]; i !=-1 ; i = edge[i].next) { if(!vis[edge[i].to]) continue; vis[edge[i].to] = false; que.push(edge[i].to); ans[edge[i].to] = ans[tem]+1; } } } int main(int argc, char const *argv[]) { memset(stu,-1,sizeof(stu)); scanf("%d",&n); int fir, las ; for (int i = 0; i < n; ++i) { scanf("%d%d",&fir,&las); addedge(fir,las); addedge(las,fir); ednum[fir]++; ednum[las]++; } bfs(); bfs2(); printf("%d",ans[1] ); for (int i = 2; i <= n; ++i) { printf(" %d",ans[i] ); } printf("\n"); return 0; }