zoukankan      html  css  js  c++  java
  • HDU 4612 Warm up

    传送门:http://acm.hdu.edu.cn/showproblem.php?pid=4612

    解题思路:

    题的大意是有N个种植园,有M条水渠相连。这就是一个强连通的无向图,他不想要这个图中存在有桥,如果添加一条边,剩余的桥的最小数量。

    本题的答案先用Tarjan进行缩点。在这个过程就可以计算出桥的数量。然后怎样添加一条边使的桥的数量最少呢? 

    答案:桥-缩点形成树的直径。

    如何求树的直径:

    有两种方法

    1. 对树进行广度优先搜索,然后以广度优先搜索最后一个访问的点进行优先搜索,然后深度优先搜索形成的这颗树的深度就是树的直径。

    2.对树进行深度优先搜索,以深度最深的点,在进行一次深度优先搜索,然后深度优先搜索形成的这颗树的深度就是就是树的直径

    注意本题有重边。

    实现代码:

      1 #include <cstdio>
      2 #include <iostream>
      3 #include <cstring>
      4 #include <algorithm>
      5 #include <vector>
      6 using namespace std;
      7 
      8 const int MAXN=200010;
      9 const int MAXM=2000010;
     10 
     11 struct Edge{
     12     int to,next;
     13     bool cut;  //标记是否是桥
     14     bool meg;  //标记是否是重边
     15 }edges[MAXM];
     16 
     17 int head[MAXN],tot;
     18 
     19 void init(){
     20     memset(head,-1,sizeof(head));
     21     tot=0;
     22 }
     23 
     24 void addEdge(int u,int v,bool meg){
     25     edges[tot].to=v;
     26     edges[tot].meg=meg;
     27     edges[tot].next=head[u];
     28     edges[tot].cut=false;
     29     head[u]=tot++;
     30 }
     31 
     32 int LOW[MAXN],DFN[MAXN],Stack[MAXN],Belong[MAXN];
     33 bool Instack[MAXN];
     34 int bridge,Index,top;
     35 int block;
     36 
     37 void Tarjan(int u,int pre,bool meg){
     38     DFN[u]=LOW[u]=++Index;
     39     Stack[top++]=u;
     40     Instack[u]=true;
     41 
     42     int v;
     43     for(int i=head[u];i!=-1;i=edges[i].next){
     44         v=edges[i].to;
     45         if(v==pre&&(!meg)) continue;
     46 
     47         if(!DFN[v]){
     48             Tarjan(v,u,edges[i].meg);
     49 
     50             if(LOW[u]>LOW[v]) LOW[u]=LOW[v];
     51 
     52             if(LOW[v]>DFN[u]){
     53                 bridge++;
     54                 edges[i].cut=true;
     55                 edges[i^1].cut=true;
     56             }
     57         }else if(Instack[v]&&LOW[u]>DFN[v]) LOW[u]=DFN[v];
     58     }
     59 
     60     if(DFN[u]==LOW[u]){
     61         block++;
     62         do{
     63             v=Stack[--top];
     64             Instack[v]=false;
     65             Belong[v]=block;
     66         }while(v!=u);
     67     }
     68 }
     69 
     70 vector<int>tree[MAXN];
     71 int dep[MAXN];
     72 
     73 //计算树的深度
     74 void dfs(int u){
     75 
     76     for(int i=0;i<tree[u].size();i++){
     77         int v=tree[u][i];
     78 
     79         if(dep[v]!=-1) continue;
     80         dep[v]=dep[u]+1;
     81         dfs(v);
     82     }
     83 }
     84 
     85 void solve(int n){
     86     memset(DFN,0,sizeof(DFN));
     87     memset(Instack,0,sizeof(Instack));
     88     Index=top=bridge=block=0;
     89 
     90 
     91     Tarjan(1,0,false);
     92     for(int i=1;i<=block;i++)
     93         tree[i].clear();
     94 
     95     for(int i=1;i<=n;i++)
     96         for(int j=head[i];j!=-1;j=edges[j].next)
     97             if(edges[j].cut)
     98                 tree[Belong[i]].push_back(Belong[edges[j].to]);
     99 
    100     memset(dep,-1,sizeof(dep));
    101     int k=1;
    102     dep[1]=0;
    103     dfs(1);
    104     for(int i=1;i<=block;i++){
    105         if(dep[k]<dep[i])
    106             k=i;
    107     }
    108 
    109     memset(dep,-1,sizeof(dep));
    110     dep[k]=0;
    111     int ans=0;
    112     dfs(k);
    113 
    114     for(int i=1;i<=block;i++)
    115         ans=max(ans,dep[i]);
    116 
    117     printf("%d
    ",bridge-ans);
    118 }
    119 
    120 struct node{
    121     int u,v;
    122     bool operator <(const node &rhs) const{
    123         if(u!=rhs.u)
    124             return u<rhs.u;
    125         else
    126             return v<rhs.v;
    127     }
    128 };
    129 
    130 node nd[MAXM];
    131 
    132 int main(){
    133     int n,m;
    134     while(scanf("%d%d",&n,&m)==2){
    135         if(n==0&&m==0) break;
    136         init();
    137 
    138         for(int i=0;i<m;i++){
    139             int u,v;
    140             scanf("%d%d",&u,&v);
    141             if(u==v) continue;
    142             if(u>v) swap(u,v);
    143             nd[i].u=u;
    144             nd[i].v=v;
    145         }
    146         sort(nd,nd+m);
    147 
    148         for(int i=0;i<m;i++){
    149             if(i==0||nd[i].u!=nd[i-1].u||nd[i].v!=nd[i-1].v){
    150                 if(i<m-1&&nd[i].u==nd[i+1].u&&nd[i].v==nd[i+1].v){
    151                     addEdge(nd[i].u,nd[i].v,true);
    152                     addEdge(nd[i].v,nd[i].u,true);
    153                 }else{
    154                     addEdge(nd[i].u,nd[i].v,false);
    155                     addEdge(nd[i].v,nd[i].u,false);
    156                 }
    157             }
    158         }
    159         solve(n);
    160     }
    161 }
    自己选的路,跪着也要把它走完------ACM坑
  • 相关阅读:
    Jzoj3555 树的直径
    Jzoj3555 树的直径
    51Nod1022 石子归并V2
    51Nod1022 石子归并V2
    Bzoj3998 弦论
    Bzoj3998 弦论
    Poj2758 Checking the Text
    Poj2758 Checking the Text
    常用SQL语句大全
    Silverlight调用GP服务第二篇之调用GP服务(Geoprocessing Service)过程详解
  • 原文地址:https://www.cnblogs.com/IKnowYou0/p/6538545.html
Copyright © 2011-2022 走看看