poj1144 求割點的個數(注意輸入的格式)
描述
電話線公司(TLC)正在建立一個新的電話電纜網路。它們連線了幾個從1到N的整數編號的位置。沒有兩個地方有相同的號碼。線路是雙向的,並且總是將兩個地方連線在一起,並且在每個地方線路終止於電話交換機。每個地方都有一個電話交換機。它來自每個地方
可以通過其他地方的線路到達,但它不需要是直接連線,它可以通過幾個交換。電源有時會在一個地方發生故障,然後交換機無法執行。TLC的官員意識到,在這種情況下,除了失敗的地方無法到達之外,還可能導致其他地方無法相互連線。在這種情況下,我們會說這個地方(
發生故障的地方 )是至關重要的。現在,官員正試圖編寫一個程式來查詢所有這些關鍵位置的數量。幫助他們。
輸入
輸入檔案由幾個行塊組成。每個塊描述一個網路。在每個塊的第一行中,存在N <100的位數。接下來最多N行中的每一行包含一個地點的數字,後面跟有來自該地方的直線的一些地方的數量。這些最多N行完全描述了網路,即,網路中兩個位置的每個直接連線至少包含在一行中。一行中的所有數字
由一個空格分隔 。每個塊以一條僅包含0的行結束。最後一個塊只有一行,N = 0;
產量
輸出包含除輸入檔案中的最後一個塊之外的每個塊,其中一行包含關鍵位置的數量。
樣本輸入
<span style="color:#000000"> 5 5 1 2 3 4 0 6 2 1 3 5 4 6 2 0 0 </span>
樣本輸出
<span style="color:#000000">
1
2
</span>
題意:
給你一個無向圖,問你這個圖中有多少個割點.不過該題的輸入格式說的比較難懂.這裡解釋一下:每個例項第一行是N,表示節點數.接下來可能有最多N行描述邊資訊的.
其中這N行每行都是這樣的:每行第一個數表示該行的主頂點u,接著的所有數字表示副頂點v1,v2,v3…等.表示u與v1,u與v2,u與v3分別都有一條邊.
最後這個例項以一個0表示結束.
當然所有例項之後還有一個0(N=0),表示輸入結束.
程式碼如下:
//求無向圖的割頂和橋
#include<cstdio>
#include<cstring>
#include<vector>
#include<iostream>
#include<cstring>
#include<string>
using namespace std;
const int maxn=1000+10;
int n,m;
int dfs_clock;//時鐘,每訪問一個節點增1
vector<int> G[maxn];//G[i]表示i節點鄰接的所有節點
int pre[maxn];//pre[i]表示i節點被第一次訪問到的時間戳,若pre[i]==0表示i還未被訪問
int low[maxn];//low[i]表示i節點及其後代能通過反向邊連回的最早的祖先的pre值
bool iscut[maxn];//標記i節點是不是一個割點
//求出以u為根節點(u在DFS樹中的父節點是fa)的樹的所有割頂和橋
//初始呼叫為dfs(root,-1);
int dfs(int u,int 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])
{
child++;//未訪問過的節點才能算是u的孩子
int lowv=dfs(v,u);
lowu=min(lowu,lowv);
if(lowv>=pre[u])
{
iscut[u]=true; //u點是割頂
/* if(lowv>pre[u]) //(u,v)邊是橋
printf("邊(%d, %d)是橋\n",u,v);*/
}
}
else if(pre[v]<pre[u] && v!=fa)//v!=fa確保了(u,v)是從u到v的反向邊
{
lowu=min(lowu,pre[v]);
}
}
if(fa<0 && child==1 )
iscut[u]=false;//u若是根且孩子數<=1,那u就不是割頂
return low[u]=lowu;
}
int main()
{
while(scanf("%d",&n)==1&&n)
{
dfs_clock=0;
memset(pre,0,sizeof(pre));
memset(iscut,0,sizeof(iscut));
for(int i=1;i<=n;i++) G[i].clear();
int a,b;
while(scanf("%d",&a)&&a)
{
while(getchar()!='\n')
{
scanf("%d",&b);
G[a].push_back(b);
G[b].push_back(a);
}
}
dfs(1,-1);
int ans=0;
for(int i=1;i<=n;i++)if(iscut[i]==true)
ans++;
cout<<ans<<endl;
}
return 0;
}