zoukankan      html  css  js  c++  java
  • 【HDU3849】求无向图的割边

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3849

    题目大意:给你一个关系网,问你那两个人是关键关系,即在整个关系网中起到链接作用,不可失去,这样对应到无向图中不就是要你求哪些边不在强连通分量中吗,即不在任何环中的边。

    解题思路: 利用tarjan算法的变形,以前用tarjan求的是有向图的强连通分量,这个是无向图,所以要进行相应的变形。

     1、 首先,要求割边则对应的图必须是连通图,如果不是连通图那么割边就是0.

     2、开始WA了几次,因为我开始这么想:一条边连接的两个顶点只要在不同的连通分量中(low[]值不同),那么这条边就是割边,好像想想有道理唉?这样是错的,因为当出现两个强连通分量共边(即理解成两个环共边时),两个顶点的low[]值可能不同。 

    割边的必要条件:low[u]!=low[v]

    割边的充分必要条件:low[u]>dfn[v] || low[v]>dfn[u]。

    View Code
     1 #include <iostream>
     2 #include <cstdio>
     3 #include <map>
     4 #include <algorithm>
     5 #include <cstring>
     6 using namespace std;
     7 
     8 const int maxn=222222;
     9 int  dfn[maxn], low[maxn], head[maxn];
    10 int  reach[maxn], next[maxn];
    11 int top, Index, edge;
    12 
    13 struct node
    14 {
    15     char s[20];
    16     friend bool operator <(const node &A, const node &B)
    17     {
    18         return strcmp(A.s,B.s)<0;
    19     }
    20 };
    21 map<node,int>mp;
    22 
    23 struct Node
    24 {
    25     node x, y;
    26     int flag;
    27 }f[maxn];
    28 
    29 void init()
    30 {
    31     memset(head,-1,sizeof(head));
    32     memset(dfn,0,sizeof(dfn));
    33     edge=0;
    34 }
    35 
    36 void addedge(int u, int v)
    37 {
    38     reach[edge]=v, next[edge]=head[u], head[u]=edge++;
    39 }
    40 
    41 void tarjan(int u, int fa)
    42 {
    43     dfn[u]=low[u]=++Index;
    44     for(int i=head[u]; i>=0; i=next[i])
    45     {
    46         int v=reach[i];
    47         if(v==fa) continue;
    48         if(!dfn[v]) tarjan(v,u), low[u]=min(low[u],low[v]);
    49         else low[u]=min(low[u],dfn[v]);
    50     }
    51 }
    52 
    53 int main()
    54 {
    55     int n, m, T;
    56     cin >> T;
    57     while(T--)
    58     {
    59         int id=0;
    60         mp.clear();
    61         scanf("%d%d",&n,&m);
    62         init();
    63         for(int i=0; i<m; i++)
    64         {
    65             f[i].flag=0;
    66             scanf("%s%s",&f[i].x.s,&f[i].y.s);
    67             if(mp.find(f[i].x)==mp.end()) mp[f[i].x]=++id;
    68             if(mp.find(f[i].y)==mp.end()) mp[f[i].y]=++id;
    69             int u=mp[f[i].x], v=mp[f[i].y];
    70             addedge(u,v), addedge(v,u);
    71         }
    72         tarjan(1,-1);
    73         bool ok=true;
    74         for(int i=1; i<=n; i++)
    75             if(!dfn[i]){  ok=false; break;  }
    76         if(!ok) puts("0");
    77         else
    78         {
    79             int ans=0;
    80             for(int i=0; i<m; i++)
    81             {
    82                 int u=mp[f[i].x], v=mp[f[i].y];
    83                 if(low[u]>dfn[v]||low[v]>dfn[u]) ans++, f[i].flag=1; ///!!!
    84             }
    85             printf("%d\n",ans);
    86             for(int i=0; i<m; i++)
    87                 if(f[i].flag) printf("%s %s\n",f[i].x.s,f[i].y.s);
    88         }
    89     }
    90     return 0;
    91 }
  • 相关阅读:
    常用的服务器简介
    PHP Proxy 负载均衡技术
    Hexo 博客Next 搭建与美化主题
    Tomcat PUT方法任意文件上传(CVE-2017-12615)
    哈希爆破神器Hashcat的用法
    内网转发随想
    Oauth2.0认证
    Github搜索语法
    记一次挖矿木马清除过程
    利用ICMP进行命令控制和隧道传输
  • 原文地址:https://www.cnblogs.com/kane0526/p/3051052.html
Copyright © 2011-2022 走看看