zoukankan      html  css  js  c++  java
  • HDU 4612 Warm up —— (缩点 + 求树的直径)

      题意:一个无向图,问建立一条新边以后桥的最小数量。

      分析:缩点以后,找出新图的树的直径,将这两点连接即可。

      但是题目有个note:两点之间可能有重边!而用普通的vector保存边的话,用v!=fa的话是没办法让重边访问的,因此,使用数组模拟邻接表的方法来储存边。

    这样,只要访问了一条边以后,令E[i].vis=E[i^1].vis=1即可,这样可以防止无向图的边和重边搞混。原理就是按位异或,一个奇数^1变为比它小1的偶数,反之亦然:如5^1=4,4^1=5。

      具体见代码:

      1 #include <stdio.h>
      2 #include <algorithm>
      3 #include <string.h>
      4 #include <stack>
      5 #include <vector>
      6 #include <set>
      7 #include <queue>
      8 //#pragma comment(linker, "/STACK:1024000000,1024000000")
      9 using namespace std;
     10 
     11 const int N = 200000+5;
     12 
     13 int n,m,dfn[N],low[N];
     14 int head[N];
     15 int tot=0;
     16 int dfs_clock;
     17 int bridge;
     18 int belong[N];
     19 int scc_cnt;
     20 int maxd;
     21 bool vis[N];
     22 vector<int> G[N];
     23 stack<int> S;
     24 
     25 struct edge
     26 {
     27     int v;
     28     int vis;
     29     int nxt;
     30 }E[2*1000000+10];
     31 
     32 void addEdge(int u,int v)
     33 {
     34     E[tot].v=v;
     35     E[tot].vis=0;
     36     E[tot].nxt=head[u];
     37     head[u]=tot++;
     38 
     39     E[tot].v=u;
     40     E[tot].vis=0;
     41     E[tot].nxt=head[v];
     42     head[v]=tot++;
     43 }
     44 
     45 void tarjan(int u)
     46 {
     47     dfn[u]=low[u]=++dfs_clock;
     48     S.push(u);
     49     for(int i=head[u];i!=-1;i=E[i].nxt)
     50     {
     51         int v = E[i].v;
     52         if(E[i].vis) continue;
     53         E[i].vis=E[i^1].vis=1;
     54 
     55         if(!dfn[v])
     56         {
     57             tarjan(v);
     58             low[u]=min(low[u],low[v]);
     59 
     60             if(low[v]>dfn[u]) bridge++;
     61         }
     62         else if(!belong[v])
     63         {
     64             low[u]=min(low[u],dfn[v]);
     65         }
     66     }
     67 
     68     if(dfn[u]==low[u])
     69     {
     70         scc_cnt++;
     71         for(;;)
     72         {
     73             int x = S.top();S.pop();
     74             belong[x] = scc_cnt;
     75             if(x==u) break;
     76         }
     77     }
     78 }
     79 
     80 void init()
     81 {
     82     memset(head,-1,sizeof(head));
     83     tot=0;
     84     memset(dfn,0,sizeof(dfn));
     85     dfs_clock=0;
     86     bridge=0;
     87     memset(belong,0,sizeof(belong));
     88     scc_cnt=0;
     89     maxd=0;
     90     for(int i=1;i<=n;i++) G[i].clear();
     91     memset(vis,0,sizeof(vis));
     92 }
     93 
     94 //找到树的直径
     95 void findMaxDeep(int u,int deep)
     96 {
     97     vis[u]=1;
     98 
     99     maxd=max(maxd,deep);
    100     for(int i=0;i<G[u].size();i++)
    101     {
    102         int v = G[u][i];
    103         if(!vis[v])
    104         {
    105             findMaxDeep(v,deep+1);
    106         }
    107     }
    108 }
    109 
    110 //用bfs来找到一个叶子节点
    111 int findRoot()
    112 {
    113     queue<int> Q;
    114     Q.push(1);
    115     vis[1]=1;
    116     int last=1;
    117     while(!Q.empty())
    118     {
    119         int x = Q.front();Q.pop();
    120         for(int i=0;i<G[x].size();i++)
    121         {
    122             int v = G[x][i];
    123             if(!vis[v])
    124             {
    125                 Q.push(v);
    126                 vis[v]=1;
    127                 last=v;
    128             }
    129         }
    130     }
    131     return last;
    132 }
    133 
    134 void solve()
    135 {
    136     for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i);
    137 
    138     //重新建图
    139     for(int i=1;i<=n;i++)
    140     {
    141         for(int j=head[i];j!=-1;j=E[j].nxt)
    142         {
    143             int v = E[j].v;
    144             int x = belong[i];
    145             int y = belong[v];
    146             if(x!=y)
    147             {
    148                 G[x].push_back(y);
    149                 G[y].push_back(x);
    150             }
    151         }
    152     }
    153 
    154     int root=findRoot();
    155     memset(vis,0,sizeof(vis));
    156 
    157     findMaxDeep(root,0);
    158 
    159     printf("%d
    ",bridge-maxd);
    160 }
    161 
    162 int main()
    163 {
    164     while(scanf("%d%d",&n,&m)==2)
    165     {
    166         if(n==0 && m==0) break;
    167         init();
    168 
    169         for(int i=1;i<=m;i++)
    170         {
    171             int u,v;
    172             scanf("%d%d",&u,&v);
    173             addEdge(u,v);
    174         }
    175 
    176         solve();
    177     }
    178 }

      但是奇怪的是,重新建图以后找叶子节点的时候,这里用G[x].size()==2不能够实现。讲道理,原理上是没错的,尽管后来发现如果缩点后只有一个点的话是个例外,但是即使排除了这个特殊情况仍然不行,,,这个问题也留着以后探讨吧。。

  • 相关阅读:
    Eclipse Alt + / 快捷键失效
    oracle nvl()函数
    搭建spring boot项目
    Maximum call stack size exceeded
    vue混入函数问题
    ASP.NET Core 2.0中的Azure Blob存储
    如何在ASP.NET Core 2.0中使用Razor页面
    将参数传递给ASP.NET Core 2.0中的中间件
    使用.net core在Ubuntu构建一个TCP服务器
    如何在ASP.NET Core Web API测试中使用Postman
  • 原文地址:https://www.cnblogs.com/zzyDS/p/5634999.html
Copyright © 2011-2022 走看看