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
原创粉丝点击