pku 1523 先求割点然后再求连同分支数量,求连同分支的时候我是把割点断开后,然后dfs求;这里容易理解,但是求割点的算法我还是看了2天。。。我太菜了,找了网上很多资料才弄明白,不容易啊!! 以下这个求连通图的模板写的简单容易明白 void DFS(int m) { dep[m] = depth; low[m] = depth; flag[m] = true; depth ++; int i; for(对于每一个从m出发的节点i){ if(没有被访问过){ DFS(i); low[m] = min(low[m],low[i]); if(low[i] >= dep[m] && m不是根节点) f[m]++; //m是割点 else if(m是根节点) son_num ++; else low[m] = min(low[m],dep[i]); } } } #include <iostream> #include <string> #include <vector> #define maxn 1001 using namespace std; int dfn[maxn],low[maxn],vis[maxn],f[maxn],vis2[maxn]; int rootson,ord; vector<int>G[maxn]; int min(int a, int b) { return a>b?b:a; } void add(int a, int b) { vis2[a] = vis2[b] = 1; G[a].push_back(b); G[b].push_back(a); } void dfs(int n) { int m,i; vis[n] = 1; dfn[n] = low[n] = ++ord; for(i = 0; i<G[n].size(); i++) { m = G[n][i]; if(!vis[m]) { dfs(m); if(n == 1)rootson++; else { low[n] = min(low[n],low[m]); if(low[m]>=dfn[n])f[n]++; } } else low[n] = min(low[n],dfn[m]); } } void dfs1(int cur) { int i; vis[cur] = 1; for(i = 0; i<G[cur].size(); i++) if(!vis[G[cur][i]])dfs1(G[cur][i]); } int main() { int i,u,v,ans,cnt = 1,p,flag; while(scanf("%d",&u)!=EOF && u!=0) { memset(vis2,0,sizeof(vis2)); for(i = 1; i<maxn; i++) G[i].clear(); scanf("%d",&v); add(u,v); while(scanf("%d",&u),u) { scanf("%d",&v); add(u,v); } memset(vis,0,sizeof(vis)); memset(f,0,sizeof(f)); flag = ord = rootson = ans = 0; dfs(1); if(rootson>1) { f[1]++; ans++; } for(i = 2; i<maxn; i++) if(f[i])ans++; printf("Network #%d/n",cnt); cnt++; for(i = 1; i<maxn; i++) { p = 0; if(f[i]) { flag = 1; memset(vis,0,sizeof(vis)); vis[i] = 1; for(int k = 1; k<maxn; k++) if(!vis[k]&&vis2[k]) { p++; dfs(k); } printf(" SPF node %d leaves %d subnets/n",i,p); } } if(!flag)printf(" No SPF nodes/n"); printf("/n"); } return 0; }