• 【UVA10972】RevolC FaeLoN (求边双联通分量)


    题意:

      给你一个无向图,要求把所有无向边改成有向边,并且添加最少的有向边,使得新的有向图强联通。

    分析:

      这题的解法还是很好想的。先用边双联通分量缩点,然后找新图中入度为0和为1的点,入度为0则ans+2,为1则ans+1,最后输出(ans+1)/2。

      注意,如果原图本来就强联通,答案为0不是1。

    在这里主要说说打边双联通的注意事项。(一开始觉得是跟点双连通差不多的,调试的时候才发现很容易疏忽导致BUG很多啊)

    1、如果有重边,则那条就不是割边了,我们很容易向上重走树枝边的反向边导致程序认为这是返祖边。在点双连通中判断一下是不是父亲即可,但边双联通不行。(因为重边对点双连通无影响,但对边双联通有影响)所以要做一个标记,走树枝边的时候把反向边也标记一下。

    2、stack中的剩余元素最后要记得pop出来。

    3、图不一定联通,要for一遍再dfs。

    4、发现(x,y)为割边的时候,(dfn[x]<dfn[y]),边双联通分量是算到y而不是x。(跟点双连通有一点不一样)

    代码如下:

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cstring>
     4 #include<iostream>
     5 #include<algorithm>
     6 #include<stack>
     7 using namespace std;
     8 #define Maxn 1010
     9 
    10 struct node
    11 {
    12     int x,y,next;
    13     bool vis;
    14 }t[2*Maxn*Maxn];int len;
    15 
    16 int first[Maxn],n,m;
    17 int dfn[Maxn],low[Maxn],cnt;
    18 int cc[Maxn],cl,sum[Maxn];
    19 stack<int > s;
    20 
    21 void ins(int x,int y)
    22 {
    23     t[++len].x=x;t[len].y=y;t[len].vis=0;
    24     t[len].next=first[x];first[x]=len;
    25 }
    26 
    27 int mymin(int x,int y) {return x<y?x:y;}
    28 
    29 void ffind(int x)
    30 {
    31     dfn[x]=low[x]=++cnt;
    32     s.push(x);
    33     for(int i=first[x];i;i=t[i].next) if(!t[i].vis)
    34     {
    35         int y=t[i].y;
    36         t[i].vis=1;t[i+(i%2==1?1:-1)].vis=1;
    37         if(!dfn[y])
    38         {
    39             ffind(y);
    40             low[x]=mymin(low[x],low[y]);
    41             if(low[y]>dfn[x])
    42             {
    43                 cl++;
    44                 while(!s.empty())
    45                 {
    46                     int z=s.top();
    47                     s.pop();
    48                     cc[z]=cl;
    49                     if(z==y) break;
    50                 }
    51             }
    52         }
    53         else low[x]=mymin(low[x],dfn[y]);
    54     }
    55 }
    56 
    57 int main()
    58 {
    59     while(scanf("%d%d",&n,&m)!=EOF)
    60     {
    61         len=0;cnt=0;cl=0;
    62         memset(first,0,sizeof(first));
    63         memset(dfn,0,sizeof(dfn));
    64         memset(cc,0,sizeof(cc));
    65         memset(sum,0,sizeof(sum));
    66         for(int i=1;i<=m;i++)
    67         {
    68             int x,y;
    69             scanf("%d%d",&x,&y);
    70             ins(x,y);ins(y,x);
    71         }
    72         if(!s.empty()) s.pop();
    73         for(int i=1;i<=n;i++)if(!dfn[i])
    74         {
    75             ffind(i);
    76             if(!s.empty())
    77             {
    78                 cl++;
    79                 while(!s.empty())
    80                 {
    81                     cc[s.top()]=cl;
    82                     s.pop();
    83                 }
    84             }
    85         }
    86          if(cl==1) {printf("0
    ");continue;}
    87         
    88         int ans=0;
    89         for(int i=1;i<=len;i++)
    90         {
    91             if(cc[t[i].x]==cc[t[i].y]) continue;
    92             sum[cc[t[i].x]]++;
    93         }
    94         for(int i=1;i<=cl;i++) if(sum[i]==1) ans++;
    95         else if(sum[i]==0) ans+=2;
    96         printf("%d
    ",(ans+1)/2);
    97     }
    98     return 0;
    99 }
    [uva10972]

    2016-03-23 13:54:57

  • 相关阅读:
    XMIND
    android studio 更新 Gradle错误解决方法
    解决下载Android Build-tools 19.1.0失败
    Android Studio怎么删除项目
    android studio 更改背景和设置字体大小
    IOS开发常用技术网站
    Gitbook安装
    深入解析AsyncTask(转)
    Android中Bitmap和Drawable(转)
    提高Android在eclipse下的编译速度
  • 原文地址:https://www.cnblogs.com/Konjakmoyu/p/5310811.html
Copyright © 2020-2023  润新知