POJ 1144 Network(割点)
题目传送门
题目中文翻译:
Description
电话线公司(TLC)正在建立一个新的电话电缆网络。 他们正在连接几个地方编号从1到N的整数。 没有两个地方有相同的号码。 这些线路是双向的,并且总是将两个地方连接在一起,并且在每个地方线路在电话交换机中结束。 每个地方都有一个电话交换台。 从每个地方都有可能通过其他地方的线路到达,但它不一定是直接连接,它可以经过几次交换。 电源不时会在某个地方出现故障,然后交换机不运行。 TLC的官员意识到,在这种情况下,除了发生故障的地方无法到达的事实之外,还会导致其他地方无法连接。 在这种情况下,我们会说这个地方(发生故障的地方)至关重要。 现在这些官员正在设法编写一个程序来查找所有这些关键地点的数量。 请帮助他们。
Input
输入文件由几个线块组成。 每个块描述一个网络。 在每个街区的第一行中有N <100的地点数目。下一个最多N行中的每一行都包含一个地方的号码,后面跟着这个地方有一条直线的地方的号码。 这些最多N行完整地描述网络,即网络中两个地方的每个直接连接至少包含在一行中。 一行中的所有数字由一个空格分隔。 每个块以包含0的行结束。最后一个块仅具有一条N = 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
Hint
您需要确定一行的末端。为了便于确定,每行结束前都没有额外的空白。
解题思路:
求割点模板.
AC代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 5 using namespace std; 6 7 int n,head[1005],tot,dfn[1005],low[1005],_tot,a,cut[1005]; 8 char k; 9 struct kkk { 10 int to,next; 11 }e[1005]; 12 13 inline void add(int x,int y) { 14 e[++tot].to = y; 15 e[tot].next = head[x]; 16 head[x] = tot; 17 } 18 19 inline void tarjan(int x) { 20 int flag = 0; 21 dfn[x] = low[x] = ++_tot; 22 for(int i = head[x];i != -1; i = e[i].next) { 23 int u = e[i].to; 24 if(!dfn[u]) { 25 tarjan(u); 26 low[x] = min(low[x],low[u]); 27 if(low[u] >= dfn[x]){ 28 flag++; 29 if(x != 1 || flag > 1) cut[x] = true; 30 } 31 } 32 else 33 low[x] = min(low[x],dfn[u]); 34 } 35 } 36 37 inline void chushihua() { 38 memset(head,-1,sizeof(head)); 39 memset(dfn,0,sizeof(dfn)); 40 memset(low,0,sizeof(low)); 41 memset(cut,false,sizeof(cut)); 42 tot = _tot = 0; 43 } 44 45 int main() { 46 while(scanf("%d",&n) == 1 && n) { 47 chushihua(); 48 while(scanf("%d",&a) == 1 && a) { 49 int b; 50 while((k = getchar()) != '\n') { 51 scanf("%d",&b); 52 add(a,b); 53 add(b,a); 54 } 55 } 56 int ans = 0; 57 for(int i = 1;i <= n; i++) 58 if(!dfn[i]) 59 tarjan(i); 60 for(int i = 1;i <= n; i++) 61 if(cut[i]) 62 ans++; 63 printf("%d\n",ans); 64 } 65 return 0; 66 }