http://codeforces.com/problemset/problem/131/D
题目大意:由n个点组成的n条边构成一个环,求n个点与环的距离(环上的点数)。
进行两次dfs。第一次dfs找出环上所有的点并标记flag,第二次对所有flag的点进行深搜并标记。
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <vector> #include <set> #include <map> #include <cmath> #include <queue> using namespace std; template <class T> void checkmin(T &t,T x) {if(x < t) t = x;} template <class T> void checkmax(T &t,T x) {if(x > t) t = x;} template <class T> void _checkmin(T &t,T x) {if(t==-1) t = x; if(x < t) t = x;} template <class T> void _checkmax(T &t,T x) {if(t==-1) t = x; if(x > t) t = x;} typedef pair <int,int> PII; typedef pair <double,double> PDD; typedef long long ll; #define foreach(it,v) for(__typeof((v).begin()) it = (v).begin(); it != (v).end ; it ++) const int N = 3030 , M = 6060; vector <int> g[N]; int flag[N]; bool vis[N]; int ok; void dfs1(int u,int f) { if(ok) return; vis[u] = 1; int sz = g[u].size(); for(int i=0;i<sz;i++) { int v = g[u][i]; if(v == f) continue; if(vis[v]) { flag[u] = 1; ok = v; return; } dfs1(v , u); if(ok) { if(ok == u) ok = -1 , flag[u] = 1; if(ok != -1) flag[u] = 1; return; } } return; } void debug(int n) { puts("debug"); for(int i=1;i<=n;i++) if(flag[i]) printf(" %d",i); puts("end of debug"); } int dep[N]; void dfs2(int u,int f,int d) { dep[u] = d; int sz = g[u].size(); for(int i=0;i<sz;i++) { int v = g[u][i]; if(v == f) continue; if(flag[v] || dep[v]) continue; dfs2(v , u , d + 1); } } int main() { int n; cin >> n; for(int i=0;i<n;i++) { int u , v ; cin >>u >> v; g[u].push_back(v); g[v].push_back(u); } dfs1(1 , -1); //debug(n); for(int i=1;i<=n;i++) { if(flag[i]) dfs2(i,-1,0); } cout << dep[1]; for(int i=2;i<=n;i++) cout << " " << dep[i]; cout << endl; return 0; }