zoukankan      html  css  js  c++  java
  • tarjin求割点

    题目: hdu3671

    http://acm.hdu.edu.cn/showproblem.php?pid=3671

    题意:给一个无向图,要求毁掉两个点,使图变得不连通,图一开始是连通的

    因为要毁掉两个点,就不是简单的求割点,再看看数据范围,点数为1000,边数为10000,Tarjan的时间复杂度为O(E),如果用枚举法,先枚举要毁掉的第一个点,再用Tarjan进行处理来找割点会不会超时呢?答案是不会,时间为O(v*E),刚好是千万级别,不超

    做法:先枚举要删除的第1个点,在原图中删除它,看看删除它后整个图的变化

            1.整个图变得不连通了(即这个点本身是割点),但是还没完要分类讨论一下

            (1).整个图变为两部分,但是两部分刚好都是一个点,那么这两个点再毁掉哪个点都好,图的连通分支数都不

    会增加,这是一个特殊情况

          例如,(1,2)(2,3)这种图,是无解的,任意毁掉两个点都无法增加图的连通分支,所以方案数为0

            (2).整个图分为两部分,但是有一部分的点数为1,另一部分大于1,那么这时候只要在较大的那部分,任意毁掉一个点(无论是不是割点都行),最后整个图都会至少被分为了两个部分

                    (如果毁掉的是割点,将分成更多份),所以这样产生的方案数是V-2

            (3).整个图分为了两个部分,两个部分的点数都大于1,那么任意在哪个部分毁掉那个点都可以(无论是不是割点都行),最后整个图都会至少分为两个部分,所以方案数为V-1

            (4).整个图被分为了三个或更多的部分,那么也是在剩下的点中任意毁掉一个点都可以(无论那个点是不是割点),方案数为V-1

                  (如果这个点刚好处于一个部分且这个部分只有它自己一个点,那么    毁掉后整个图的分支数减1;如果这个点在一个部分且这个部分不止它一个点且这个点不是割点,那么分支数  不会增加,如果是割点分支数为增加)

         2.删除第一个点后,整个图还是连通的(是连通,不是双连通)

            那么就在剩下的图中找割点,找到几个,方案数就是多少

    最后注意一点,这样计算的结果,很容易想到是有重复的,但是不难想到,其实刚好重复了一次,因为对于一个图,方案是固定的,枚举了所有点,找出了所有已方案,相当于每个方案算了两次,最后答案除2即可

     1 #include<iostream>
     2 #include<cstring>
     3 //#include<bits/stdc++.h>
     4 #include<math.h>
     5 #include<algorithm>
     6 #include<queue>
     7 #include<stack>
     8 #include<cstdio>
     9 #include<map>
    10 #include<set>
    11 #define  si(a)       scanf("%d",&a)
    12 #define  sl(a)       scanf("%lld",&a)
    13 #define  sii(a,b)    scanf("%d%d",&a,&b)
    14 #define  sll(a,b)    scanf("%lld%lld",&a,&b)
    15 #define  queues      priority_queue
    16 #define mod 1000000007
    17 #define mem(a)  memset(a,0,sizeof(a));
    18 #define def(a) ((a)&(-a))
    19 #define mp make_pair
    20 #define pb push_back
    21 #define  fi first
    22 #define se second
    23 typedef long long ll;
    24 const int INF=0x3f3f3f3f;
    25 using namespace std;
    26 const int MAX=1003;
    27 vector<int>q[MAX];
    28 int DFN[MAX];
    29 int VIM[MAX];
    30 int top;
    31 int clore;
    32 int num;
    33 set<int>s;
    34 void tarjan(int a,int fa,int d)
    35 {
    36     int child=0;
    37     DFN[a]=VIM[a]=++top;
    38     num++;
    39     for(int i:q[a])
    40     {
    41         if(i==fa||i==d)continue;
    42         if(!DFN[i])
    43         {
    44             child++;
    45             tarjan(i,a,d);
    46             VIM[a]=min(VIM[a],VIM[i]);
    47             if(VIM[i]>=DFN[a]&&a!=fa)
    48                 s.insert(a);
    49         }
    50         else VIM[a]=min(VIM[a],DFN[i]);
    51     }
    52     if(a==fa&&child>=2)s.insert(a);
    53 }
    54 int main()
    55 {
    56     int n,m;
    57     int z=0;
    58     while(cin>>n>>m&&n+m)
    59     {
    60         int sum=0;
    61         top=0;
    62         for(int i=1; i<=n; i++)
    63             q[i].clear();
    64         for(int i=1; i<=m; i++)
    65         {
    66             int a,b;
    67             cin>>a>>b;
    68             q[a].push_back(b);
    69             q[b].push_back(a);
    70         }
    71         for(int i=1; i<=n; i++)
    72         {
    73             int count1=0;
    74             int ok=0;
    75             clore=0;
    76             s.clear();
    77             mem(VIM);
    78             mem(DFN);
    79             for(int j=1; j<=n; j++)
    80                 if(j!=i&&!DFN[j])
    81                 {
    82                     count1++;
    83                     num=0;
    84                     tarjan(j,j,i);
    85                     if(num==1)ok++;
    86                 }
    87             if(count1>=3)sum+=n-1;
    88             else if(count1==2&&ok==1)sum+=n-2;
    89             else if(count1==2&&ok==0)sum+=n-1;
    90             else if(count1==1)sum+=s.size();
    91         }
    92         printf("Case %d: %d
    ",++z,sum/2);
    93     }
    94 
    95 }
    View Code
  • 相关阅读:
    友盟上报 IOS
    UTF8编码
    Hill加密算法
    Base64编码
    Logistic Regression 算法向量化实现及心得
    152. Maximum Product Subarray(中等, 神奇的 swap)
    216. Combination Sum III(medium, backtrack, 本类问题做的最快的一次)
    77. Combinations(medium, backtrack, 重要, 弄了1小时)
    47. Permutations II(medium, backtrack, 重要, 条件较难思考)
    3.5 find() 判断是否存在某元素
  • 原文地址:https://www.cnblogs.com/zxz666/p/10722663.html
Copyright © 2011-2022 走看看