hdu 3671无向图割点

感想:在做题的时候如果能够规划好,按自己的规划写代码bug出现的几率会少很多。 本来以为这道题会消耗我很长时间,结果很快就过了。

题意: 给出一个无向图,现在可以去点两个点想让剩下的图不再连通,问一共有多少种情况。

思路: 我的做法是枚举一个去掉的点,

如果剩下的图分成3部分(或大于三部分), 那么答案就要加n-1。

如果分成两部分,那么如果两部分的点的个数都不为1,那么结果要加n-1。

                       如果有一个为1,那么要加n-2,如果都为1,那么不加

如果剩下一部分,就按无向图求割点的方法求出。具体求法是这样

                      如果是根节点那么至少有两个子节点, 如果是其他点那么至少有一个子节点的low[v]>=lp[u]

AC代码:

View Code
  1 #include <cstdio>
  2 #include <cstring>
  3 #include <string>
  4 #include <iostream>
  5 #include <algorithm>
  6 using namespace std;
  7 const int N = 1050, M = 21000;
  8 struct EDGE
  9  {
 10      int u, v, next;
 11  }edge[M];
 12 
 13 int num, head[N], low[N], lp[N], step;
 14 int n, m, ans=0, f, root;
 15 
 16 void add(int u, int v)
 17  {
 18      edge[num].u = u;
 19      edge[num].v = v;
 20      edge[num].next = head[u];
 21      head[u] = num++;
 22  }
 23 
 24 void init()
 25  {
 26      num = 0;
 27      memset(head, -1, sizeof(head));
 28      int u, v;
 29      for(int i=0; i<m; i++)
 30      {
 31          scanf("%d%d", &u, &v);
 32          add(u, v);
 33          add(v, u);
 34      }
 35  }
 36 
 37 int tarjan(int u)
 38  {
 39      lp[u] = low[u] = ++step;
 40      int tp = 0,v, cc=1;
 41      bool flag = 0;
 42      for(int i = head[u];i != -1;i = edge[i].next)
 43       {
 44           v = edge[i].v;
 45           if(v == f) continue;
 46           if(!lp[v])
 47            {
 48                cc++;
 49                tp++;
 50                tarjan(v);
 51                low[u] = min(low[u],low[v]);
 52                if(u != root&&lp[u] <= low[v])
 53                 flag = 1;
 54            }
 55           else low[u] = min(low[u],lp[v]);
 56       }
 57       if(u == root && tp > 1)
 58        flag = 1;
 59       if(flag) ans++;
 60       return cc;
 61  }
 62 
 63 
 64 void solve()
 65  {
 66      int result = 0;
 67      int now, path[N] = {0};
 68      for(int i=1; i<=n; i++)
 69       {
 70           memset(low, 0, sizeof(low));
 71           memset(lp, 0, sizeof(lp));
 72           step = 1;
 73           now = ans = 0;
 74           f = i;
 75           for(int j=1; j<=n; j++)
 76            {
 77                if(!lp[j] && j!=i)
 78                 {
 79                     root = j;
 80                     path[++now] = tarjan(j);
 81                 }
 82            }
 83          if(now > 2) result += n-1;
 84          else if(now == 2)
 85           {
 86               sort(path+1, path+3);
 87               if(path[1] == 1)
 88                {
 89                    if(path[2] != 1)
 90                     result += n-2;
 91                }
 92               else  result += n-1;
 93           }
 94          else result += ans;
 95       }
 96      printf("%d\n", result/2);
 97  }
 98 
 99 int main()
100  {
101      int t=0;
102      while(scanf("%d%d", &n, &m) != EOF)
103       {
104           if(n==0 && m==0)
105            break;
106           init();
107           t++;
108           printf("Case %d: ", t);
109           solve();
110       }
111      return 0;
112  }
posted @ 2012-10-24 16:30  Gu Feiyang  阅读(559)  评论(0)    收藏  举报