題目鏈接:http://acm.hrbust.edu.cn/index.php?m=ProblemSet&a=showProblem&problem_id=1494
網絡
Time Limit: 1000 MS Memory Limit: 65535 K
Total Submit: 177(57 users) Total Accepted: 92(55 users) Rating: Special Judge: No
Description
一個電話公司建立了一個新的電話網,他們用1——N的整數標記了一些地方,每個地方有唯一的編號,網絡中的每條電纜雙向連接了兩個地方,從每個地方可以通過電纜連接到任意其他的地方,因爲它們之間不一定要有直接相連的電纜,可以通過其他的電纜間接連接,有的時候某個地方的電力可能會中斷,從而導致這個地方無法被連接,電話公司意識到了某些地方的電力中斷可能會導致其他地方也無法互相連接,把這些地方叫做關鍵點,所以他們決定寫一個程序去找到這些地方。
Input
每組輸入是一個電話網絡,每組的第一行是一個整數N<100,表示電話網絡連接了N個地點,接下來是不超過N行整數,每行表示第一個整數與後面的整數表示的地點之間有電纜直接相連,每組數據以0結束,輸入也以0結束。
Output
輸出關鍵點的數量
Sample Input
5
5 1 2 3 4
0
6
2 1 3
5 4 6 2
0
0
Sample Output
1
2
【思路分析】同http://blog.csdn.net/qq_32866009/article/details/77102615
【AC代碼】
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
using namespace std;
vector<int>G[105];//存無向圖
int iscut[105],pre[105],low[105];//iscut[i]i點是否爲割點,pre[i]當前節點是否被訪問過,low[i]爲i及i的後代所能連回的最早的祖先的pre值
int dfs_clock;
int dfs(int u,int fa)//u在DFS樹中的父節點是fa
{
int lowu = pre[u] = ++dfs_clock;
int child = 0;//子節點的數目
for(int i = 0;i < G[u].size(); i++)
{
int v = G[u][i];
if(!pre[v])//沒有訪問過v
{
child++;
int lowv = dfs(v,u);
lowu = min(lowu, lowv);//用後代的low函數更新u的low函數
if(lowv >= pre[u])
{
iscut[u] = true;
}
}
else if(pre[v] < pre[u] && v != fa)//子節點在u之前被訪問,並且子節點不是u的父節點
{
lowu = min(lowu,pre[v]);//用反向邊更新u的low函數
}
}
if(fa < 0 &&child == 1) iscut[u] = 0;//如果u是根節點只有一個子節點的話,那麼u一點是割點
low[u] = lowu;
return lowu;
}
int main()
{
int n;
while(~scanf("%d",&n))
{
for(int i=0;i<=n;i++)
{
G[i].clear();
}
if(n==0)break;
int a,b;
while(scanf("%d",&a)&&a)
{
while(getchar()!='\n')
{
scanf("%d",&b);
G[a].push_back(b);
G[b].push_back(a);
}
}
memset(pre,0,sizeof(pre));
memset(iscut,0,sizeof(iscut));
memset(low,0,sizeof(low));
dfs_clock=0;
dfs(1,-1);
int cnt=0;
for(int i=1;i<=n;i++)
{
if(iscut[i])cnt++;
}
printf("%d\n",cnt);
}
return 0;
}