zoj1311
来源:互联网 发布:postscript软件下载 编辑:程序博客网 时间:2024/04/30 22:55
题目大意:
TLC电话线路公司正在新建一个电话线路网络。他们将一些地方(这些地方用1~N的整数标明,任何两个地方的标号都不相同)用电话线路连接起来。这些线路是双向的,每条线路连接两个地方,并且每个地方的电话线路都连接到一个电话交换机。每个地方都有一个电话交换机。从每个地方都可以到达其他一些地方(如果有线路连接的话),然而这些线路不一定必须是直接连接的,也可以是通过几个电话交换机到达另外一个地方。但是有时会因为电力不足导致某个地方的交换机不能工作。TLC的官员意识到一旦出现这种情况(在某个地方的交换机不工作,即这个结点与其他结点之间的线路都断开了),除了这个出现故障的地方是不可达外,还可能导致其他一些(本来连通的)地方也不再连通。称这个地方为关节点。
现在TLC的官员努力想写一个程序来找到关节点的数目。请帮助他们。
解题思路:
求无向图的割点,tarjan算法
代码如下:
#include<cstdio>#include<cstring>#define MAXN 105int Edge[MAXN][MAXN];int visited[MAXN];int n;int tmpfn;int dfn[MAXN];int low[MAXN];int son;int critical;int subnet[MAXN];int min(int a,int b){ if(a>b) return b; else return a;}void dfs(int u){ for(int v=1;v<=n;v++) { if(Edge[u][v]) { if(!visited[v]) { visited[v]=1; tmpfn++; dfn[v]=low[v]=tmpfn; dfs(v); low[u]=min(low[u],low[v]); if(low[v]>=dfn[u]) { if(u!=1&&!subnet[u]) { subnet[u]=1; critical++; } if(u==1) son++; } } else low[u]=min(low[u],dfn[v]); } }}void init(){ low[1]=dfn[1]=1; tmpfn=1; son=0; memset(visited,0,sizeof(visited)); visited[1]=1; critical=0; memset(subnet,0,sizeof(subnet));}int main(){ int i; int u,v; while(scanf("%d",&n),n) { getchar(); memset(Edge,0,sizeof(Edge)); char buf[128]; int u,v; while(1) { int k=0; int first=1; gets(buf); while(sscanf(buf+k,"%d",&v)==1) { if(first) { first=0;u=v; } else Edge[u][v]=Edge[v][u]=1; while(buf[k]&&buf[k]==' ') k++; while(buf[k]&&buf[k]!=' ') k++; } if(u==0) break; } init(); dfs(1); if(son>1) critical++; printf("%d\n",critical); } return 0;}
0 0