zoukankan      html  css  js  c++  java
  • hdu 4612 边双联通 ***

    题意:有N 个点,M条边,加一条边,求割边最少。(有重边)

    链接:点我

    先求双连通分量,缩点形成一个生成树,然后求这个的直径,割边-直径即是答案

      1 #pragma comment(linker, "/STACK:1024000000,1024000000")
      2 #include <stdio.h>
      3 #include <string.h>
      4 #include <iostream>
      5 #include <algorithm>
      6 #include <map>
      7 #include <vector>
      8 using namespace std;
      9 
     10 const int MAXN = 200010;//点数
     11 const int MAXM = 2000010;//边数,因为是无向图,所以这个值要*2
     12 
     13 
     14 
     15 
     16 struct Edge
     17 {
     18     int to,next;
     19     bool cut;//是否是桥标记
     20     bool cong;
     21 }edge[MAXM];
     22 int head[MAXN],tot;
     23 int Low[MAXN],DFN[MAXN],Stack[MAXN],Belong[MAXN];//Belong数组的值是1~block
     24 int Index,top;
     25 int block;//边双连通块数
     26 bool Instack[MAXN];
     27 int bridge;//桥的数目
     28 
     29 void addedge(int u,int v,bool pp)
     30 {
     31     edge[tot].to = v;edge[tot].next = head[u];edge[tot].cut=false;
     32     edge[tot].cong = pp;
     33     head[u] = tot++;
     34 }
     35 
     36 void Tarjan(int u,int pre,bool ff)
     37 {
     38     int v;
     39     Low[u] = DFN[u] = ++Index;
     40     Stack[top++] = u;
     41     Instack[u] = true;
     42     for(int i = head[u];i != -1;i = edge[i].next)
     43     {
     44         v = edge[i].to;
     45         if(v == pre && (!ff))continue;  //有重边
     46         if( !DFN[v] )
     47         {
     48             Tarjan(v,u,edge[i].cong);
     49             if( Low[u] > Low[v] )Low[u] = Low[v];
     50             if(Low[v] > DFN[u])
     51             {
     52                 bridge++;
     53                 edge[i].cut = true;
     54                 edge[i^1].cut = true;
     55             }
     56         }
     57         else if( Instack[v] && Low[u] > DFN[v] )
     58             Low[u] = DFN[v];
     59     }
     60     if(Low[u] == DFN[u])
     61     {
     62         block++;
     63         do
     64         {
     65             v = Stack[--top];
     66             Instack[v] = false;
     67             Belong[v] = block;
     68         }
     69         while( v!=u );
     70     }
     71 }
     72 void init()
     73 {
     74     tot = 0;
     75     memset(head,-1,sizeof(head));
     76 }
     77 
     78 int du[MAXN];//缩点后形成树,每个点的度数
     79 vector<int>vec[MAXN];
     80 int dep[MAXN];
     81 void dfs(int u)
     82 {
     83     for(int i = 0;i < vec[u].size();i++)
     84     {
     85         int v = vec[u][i];
     86         if(dep[v]!=-1)continue;
     87         dep[v]=dep[u]+1;
     88         dfs(v);
     89     }
     90 }
     91 void solve(int n)
     92 {
     93     memset(DFN,0,sizeof(DFN));
     94     memset(Instack,false,sizeof(Instack));
     95     Index = top = block = 0;
     96     Tarjan(1,0,false);
     97     for(int i = 1;i <= block;i++)
     98         vec[i].clear();
     99     for(int i = 1;i <= n;i++)
    100        for(int j = head[i];j != -1;j = edge[j].next)
    101           if(edge[j].cut)
    102           {
    103               vec[Belong[i]].push_back(Belong[edge[j].to]);
    104           }
    105     memset(dep,-1,sizeof(dep));
    106     dep[1]=0;
    107     dfs(1);
    108     int k = 1;
    109     for(int i = 1;i <= block;i++)
    110         if(dep[i]>dep[k])
    111           k = i;
    112     memset(dep,-1,sizeof(dep));
    113     dep[k]=0;
    114     dfs(k);
    115     int ans = 0;
    116     for(int i = 1;i <= block;i++)
    117         ans = max(ans,dep[i]);
    118     printf("%d
    ",block-1-ans);
    119 }
    120 struct NN
    121 {
    122     int u,v;
    123 }node[MAXM];
    124 bool cmp(NN a,NN b)
    125 {
    126     if(a.u != b.u)return a.u<b.u;
    127     else return a.v<b.v;
    128 }
    129 int main()
    130 {
    131     //freopen("in.txt","r",stdin);
    132     //freopen("out.txt","w",stdout);
    133     int n,m;
    134     int u,v;
    135     while(scanf("%d%d",&n,&m)==2)
    136     {
    137         if(n==0 && m==0)break;
    138         init();
    139         for(int i = 0;i < m;i++)
    140         {
    141             scanf("%d%d",&u,&v);
    142             if(u==v)continue;
    143             if(u>v)swap(u,v);
    144             node[i].u = u;
    145             node[i].v = v;
    146         }
    147         sort(node,node+m,cmp);
    148         for(int i = 0;i < m;i++)
    149         {
    150             if(i == 0 || (node[i].u!=node[i-1].u || node[i].v != node[i-1].v))
    151             {
    152                 if(i < m-1 && (node[i].u==node[i+1].u && node[i].v == node[i+1].v))     //标记了是否出现重边
    153                 {
    154                     addedge(node[i].u,node[i].v,true);
    155                     addedge(node[i].v,node[i].u,true);
    156                 }
    157                 else
    158                 {
    159                     addedge(node[i].u,node[i].v,false);
    160                     addedge(node[i].v,node[i].u,false);
    161                 }
    162             }
    163         }
    164         solve(n);
    165     }
    166     return 0;
    167 }
    2015/7/3
  • 相关阅读:
    Visual Studio日志
    选择jQuery的理由
    第三方开发者可将JIT和编译器引入WinRT吗?
    Visual Studio 2012和.NET 4.5已经就绪!
    500TB——Facebook每天收集的数据量
    Netflix开源他们的另一个架构——Eureka
    PhoneGap 2.0 发布
    快速哈希算法破坏了加密的安全性
    Blend for Visual Studio 2012:为Windows 8应用所用的UX工具
    系统中的故障场景建模
  • 原文地址:https://www.cnblogs.com/cnblogs321114287/p/4617778.html
Copyright © 2011-2022 走看看