poj 2117 Electricity

题目大意:有n个核电站,去掉一个核电站,最多能把剩下的分成几块。

解题思路:求出每个子图的割顶和能判断出这个割顶的儿子数,算出每个割顶能把子块分成几块。最后加上本来图的块数。

先是终止条件写错了,一直OLE,样例居然能过。。。然后就是求割顶能把图分成多少块的地方少加了1,最后在输出的时候加上应该也一样。。

但是有个地方没搞懂的,假设一个子图被一个割顶分成了k+1份,那么能确定这个点是割顶的儿子数就是k(SPFnumber里面存的值),一个图本身有t块,那么去掉这个割顶能产生的块数应该等于k+1+t-1=k+t块,为什么结果是k+t+1呢。。。。难道SPFNumber里面存的就是一坨翔?(一堆废话,我的心情很复杂。。。)

最后发现原来SPFNumber里面的数据,每处理一组数据的时候初值为-1,最后结果不少一才怪。。。

#include <iostream>
#include <cstdio>
#include <cstdlib>
using namespace std;

int low[11000],dep[11000];
int SPFNumber[11000];//求割顶被求次数,用来求去掉割顶后分成多少联通块 
int boo[11000];//染色标记 
int deep;//给图上所有点按照遍历顺序标号,每个点的标号不重记 
int bridge;//求桥的数量 
int tip;
int n,m;

//邻接表 
int now[11000],test=0;
int tail;
class PPP
{
      public:
       int point;
       int next;
}way[100000];
void clearlist()
{
     tail = 0;
     memset(now,0,sizeof(now));
     memset(SPFNumber,0,sizeof(SPFNumber));
     memset(boo,0,sizeof(boo));
}
void insert(int a,int b)
{
     tail++;
     way[tail].point = b;
     way[tail].next = now[a];
     now[a] = tail;
}

//基于深搜的标记法求割顶与桥 
void dfs(int k,int father)
{
     int son; 
     boo[k] = 1;
     dep[k] = ++deep;
     low[k] = dep[k];
     for (int i = now[k] ; i != 0 ; i = way[i].next)
     {
         son = way[i].point;
         if (son == father) continue;
         if (boo[son]) {
                        low[k] = low[k]<dep[son]?low[k]:dep[son];
                        continue;
                       }
         dfs(son,k);
         low[k] = low[k]<low[son]?low[k]:low[son];
         if (low[son] >= dep[k]) SPFNumber[k] ++;
         if (low[i] > dep[k]) bridge ++;
         
     }
}

int main()
{
    //freopen("a.txt","r",stdin);
    //freopen("my.txt","w",stdout);
    int x,y,ans,sum;
while (1)
{
      deep = 0;
      clearlist();
      scanf("%d%d",&n,&m);
      if (n == 0 && m == 0) break;
      for (int i = 1 ; i <= m ; i ++)
      {
          scanf("%d%d",&x,&y);
          insert(x,y);
          insert(y,x);
      }
      bridge = 0;
      sum = 0;
      ans = -99999; 
      for (int i = 0 ; i < n ; i ++)
      {
          if (boo[i] == 1) continue;
          dfs(i,-1);
          SPFNumber[i] --;
          sum++;
      }
      for (int i = 0 ; i < n ; i ++)
          ans = ans>SPFNumber[i]?ans:SPFNumber[i];
      printf("%d\n",ans+sum);
}
return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值