LOJ10100

原题来自:CEOI 1996

一个电话线公司(简称 TLC)正在建立一个新的电话线缆网络,他们连接了若干个地点,编号分别从 1 到 N,没有两个地点有相同的号码,这些线是双向的并且能使两个地点保持通讯,每个地点的线都终结于电话交换机。每个地点都有一个电话交换机。从每个地点都能通过线缆到达其他任意的地点,然而它并不需要直接连接,它可以通过若干个交换机来到达目的地。

有时候某个地点供电出问题时,交换机就会停止工作。TLC 的工作人员意识到,除非这个地点是不可达的,否则这种情况就会发生,它还会导致一些其它的地点不能互相通讯。在这种情况下我们会称这个地点(错误发生的地方)为灾区。现在工作人员想要写一个程序统计所有灾区的数量。帮帮他们。

输入格式

输入文件包括若干组测试数据。

每一组是一个网络,每一组测试数据的第一行是地点的总数量 N。每组接下来最多有 N 行包括一个数字表示一个地点和与它相连接的地点的数字。最多 N 行可以完全描述整个网络,比如,网络中每个直接连接的两个地点被至少一行包括。一行内的所有数字都要用空格隔开。每组数据需要用单独的一个 0 结束。最后的块只有一行即 N=0

输出格式

输出除了最后一组,其他每一组的灾区的数量,每个块用一行输出。

样例
样例输入
5
5 1 2 3 4
0
6
2 1 3
5 4 6 2
0
0
样例输出
1
2
数据范围与提示
 N<100
 ___________________________________________________________
 
求割点的模板题目。

___________________________________________________________

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=105;
 4 int n;
 5 struct edge
 6 {
 7     int u,v,nxt;
 8 }e[maxn*maxn];
 9 int head[maxn],js;
10 void addage(int u,int v)
11 {
12     e[++js].u=u;e[js].v=v;
13     e[js].nxt=head[u];head[u]=js;
14 }
15 int low[maxn],dfn[maxn],cnt,st[maxn],top,lts;
16 bool cut[maxn];
17 vector<int>lt[maxn];
18 void tarjan(int u,int rt)
19 {
20     low[u]=dfn[u]=++cnt;
21     st[++top]=u;
22     int ct=0;
23     for(int i=head[u];i;i=e[i].nxt)
24     {
25         int v=e[i].v;
26         if(!dfn[v])
27         {
28             ct++;
29             tarjan(v,rt);
30             low[u]=min(low[u],low[v]);
31             if((ct>1 && u==rt)||(u!=rt && low[v]>=dfn[u]))cut[u]=1;
32 /*
33             if(low[v]>=dfn[u])
34             {
35                 lts++;
36                 lt[lts].clear();
37                 while(st[top]!=u)lt[lts].push_back(st[top--]);
38                 lt[lts].push_back(u);
39             }
40 */            
41         }
42         else low[u]=min(low[u],dfn[v]);
43     }
44 }            
45 void init()
46 {
47     memset(head,0,sizeof head);
48     js=0;
49     memset(low,0,sizeof low);
50     memset(dfn,0,sizeof dfn);
51     cnt=0;
52     top=0;
53     lts=0;
54     memset(cut,0,sizeof cut);
55     
56 }
57 int main()
58 {
59     while(scanf("%d",&n),n)
60     {
61         init();
62         int u,v;
63         while(scanf("%d",&u),u)
64         {
65             while(1)
66             {
67                 scanf("%d",&v);
68                 addage(u,v);addage(v,u);
69                 char c=getchar();
70                 if(c=='\n')break;
71             }
72         }
73         for(int i=1;i<=n;++i)
74             if(!dfn[i])tarjan(i,i);
75         int jss=0;
76         for(int i=1;i<=n;++i)if(cut[i])jss++;
77         printf("%d\n",jss);
78     }    
79     return 0;
80 }
View Code

 

转载于:https://www.cnblogs.com/gryzy/p/10998464.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值