• 【HDU4612】 双连通分量求桥


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

    题目大意:给你一个无向图,问你加一条边后最少还剩下多少多少割边。

    解题思路:好水的一道模板题。先缩点变成一颗树,再求树的最长直径,直径两端连一条边就是最优解了。

                  但是....我WA了一个下午.....没有处理重边。

                 重边的正确处理方法:只标记已经走过的正反边,而不限制已走过的点。换句话说就是可以经过重边再次走向父亲节点,而不能经过走过边的反向边返回父亲节点。

      1 #pragma comment(linker, "/STACK:1024000000,1024000000")
      2 #include <iostream>
      3 #include <cstdio>
      4 #include <queue>
      5 #include <algorithm>
      6 #include <cstring>
      7 using namespace std;
      8 
      9 const int maxn=222222;
     10 const int maxm=2222222;
     11 int  dfn[maxn], low[maxn], head[maxn], stack[maxn], instack[maxn], belong[maxn];
     12 int  reach[maxm], next[maxm], sign[maxm];
     13 int  visit[maxn];
     14 int  top, Index, scnt, edge, pos, bridgenum;
     15 int  n, m;
     16 pair<int,int>num[maxm];
     17 
     18 struct node
     19 {
     20     int u;
     21     int dis;
     22     int fa;
     23 };
     24 queue<node>q;
     25 
     26 void init()
     27 {
     28     memset(head,-1,sizeof(head));
     29     memset(dfn,0,sizeof(dfn));
     30     memset(instack,0,sizeof(instack));
     31     Index=top=edge=scnt=bridgenum=0;
     32 }
     33 
     34 void addedge(int u, int v)
     35 {
     36     sign[edge]=0, reach[edge]=v, next[edge]=head[u], head[u]=edge++;
     37     sign[edge]=0, reach[edge]=u, next[edge]=head[v], head[v]=edge++;
     38 }
     39 
     40 void tarjan(int u)
     41 {
     42     stack[++top]=u;
     43     dfn[u]=low[u]=++Index;
     44     instack[u]=1;
     45     for(int i=head[u]; i>=0; i=next[i])
     46     {
     47         if(sign[i]) continue;
     48         sign[i]=1, sign[i^1]=1;  ///处理重边,只标记边,而不限制点
     49         int v=reach[i];
     50         if(!dfn[v])
     51         {
     52             tarjan(v), low[u]=min(low[u],low[v]);
     53             if(dfn[u]<low[v]) bridgenum++;  ///求桥的数量
     54         }
     55         else if(instack[v]) low[u]=min(low[u],dfn[v]);
     56     }
     57     if(low[u]==dfn[u])
     58     {
     59         int v;
     60         scnt++;   ///双连通分量的数量
     61         do
     62         {
     63             v=stack[top--];
     64             instack[v]=0;
     65             belong[v]=scnt;
     66         }
     67         while(u!=v);
     68     }
     69 }
     70 
     71 int bfs(int st)
     72 {
     73     int maxx=0;
     74     while(!q.empty()) q.pop();
     75     memset(visit,0,sizeof(visit));
     76     node s, p;
     77     s.u=st, s.dis=0, s.fa=-1;
     78     q.push(s);
     79     visit[s.u]=1;
     80     while(!q.empty())
     81     {
     82         p=q.front();
     83         q.pop();
     84         for(int i=head[p.u]; i>=0; i=next[i])
     85         {
     86             int v=reach[i];
     87             if(v==p.fa) continue;
     88             s.u=v, s.dis=p.dis+1, s.fa=p.u;
     89             if(!visit[s.u])
     90             {
     91                 visit[s.u]=1, q.push(s);
     92                 if(s.dis>maxx)
     93                 {
     94                     maxx=s.dis;
     95                     pos=s.u;
     96                 }
     97             }
     98         }
     99     }
    100     return maxx;
    101 }
    102 
    103 void Solve()
    104 {
    105     memset(head,-1,sizeof(head));
    106     edge=0;
    107     for(int i=1; i<=m; i++)
    108     {
    109         int u=num[i].first, v=num[i].second;
    110         int x=belong[u], y=belong[v];
    111         if(x!=y) addedge(x,y);
    112     }
    113     bfs(1);
    114     int ans=bfs(pos);
    115     cout << bridgenum-ans <<endl;
    116 }
    117 
    118 int main()
    119 {
    120     while(cin >> n >> m, n+m)
    121     {
    122         init();
    123         for(int i=1; i<=m; i++)
    124         {
    125             int u, v;
    126             scanf("%d%d",&u,&v);
    127             num[i].first=u, num[i].second=v;
    128             addedge(u,v);
    129         }
    130         for(int i=1; i<=n; i++)
    131             if(!dfn[i]) tarjan(i);
    132         Solve();
    133     }
    134     return 0;
    135 }
    136 
    137 /*
    138 10 11
    139 1 2
    140 2 3
    141 3 4
    142 2 4
    143 3 6
    144 5 10
    145 5 7
    146 7 8
    147 8 9
    148 7 9
    149 3 5
    150 */
    View Code
  • 相关阅读:
    洛谷P2336 喵星球上的点名
    脚本的含义,什么是脚本应用场景
    redis 事务
    redis缓存
    小程序跳转到另一个小程序
    laravel安装Excel安装不上
    小程序模板中data传值有无...
    thinkphp5.0写的项目放到服务器上 lnmp 404
    使用xshell远程连接
    小程序中this和that用法
  • 原文地址:https://www.cnblogs.com/kane0526/p/3221144.html
Copyright © 2020-2023  润新知