zoukankan      html  css  js  c++  java
  • hdu 4612 无向图连通分量缩点,然后求树的最大直径

    #pragma comment(linker,"/STACK:102400000,102400000")
    #include <iostream>
    #include <queue>
    #include <cstdio>
    #include <vector>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int maxn = 200100;
    const int maxm = 2000100;
    struct node{
        int v,next;
    }edge[maxm];
    struct Bridge
    {
        int u,v;
    }bridge[maxm];
    int head[maxn],vis[maxm],fa[maxn],dfn[maxn],low[maxn],stack[maxn],in[maxn];
    int id,time,num,total,top,ans;
    void add_edge(int u,int v)
    {
        edge[id].v = v;edge[id].next = head[u],head[u] = id++;
        edge[id].v = u;edge[id].next = head[v],head[v] = id++;
    }
    int min(int x,int y)
    {
        return x < y ? x : y;
    }
    void tarjan(int u)
    {//无向图找桥并缩点
        low[u] = dfn[u] = ++time;
        stack[top++] = u;
        for(int id = head[u] ; id != -1; id = edge[id].next)
        {
            int v =edge[id].v;
            if(vis[id])continue;
            vis[id] = vis[id^1] = 1;
            if( !dfn[v] )
            {
                tarjan(v);
                low[u] = min(low[u],low[v]);
                if( low[v] > dfn[u])//u经过v不能回到u,则u与v之间存在桥
                {
                    bridge[total].u = u;
                    bridge[total++].v = v;
                }
            }
            low[u] = min(low[u],dfn[v]);
        }
        if(low[u] == dfn[u])
        {//对连通分量进行缩点
            num++;
            int t;
            do{
                t = stack[--top];
                fa[t] = num;
            }while( t != u);
        }
    }
    vector<int>g[maxn];
    
    int dfs(int u)
    {//求树的最大直径
        vis[u]=1;
        int i,j,temp=0,Max=0,lMax=0;//Max为以u为根,u到的最远的叶子节点的距离,lMax为次最远距离
        for(i = 0; i < g[u].size() ; i++ ){
            int v = g[u][i];
            if(vis[v])continue;
            temp=dfs(v);
            if(temp+1>=Max){
                lMax=Max;
                Max=temp+1;
            }
            else
                if(temp+1>lMax)
                    lMax=temp+1;
            if(Max+lMax>ans)
                ans=Max+lMax;
        }
        return Max;
    }
    
    int max_len()
    {//求树的最大直径
        int res = 0;
        memset(vis,0,sizeof(vis));
        queue<int>que;
        que.push(1);
        vis[1] = 1;
        int tmp;
        while( !que.empty())
        {
            int u = que.front();
            que.pop();
            tmp = u;
            for( int i = 0 ; i < g[u].size(); i++)
            {
                int v = g[u][i];
                if( vis[v] )continue;
                vis[v] = 1;
                que.push(v);
            }
        }
    
        queue<pair<int,int> >que1;
        memset(vis,0,sizeof(vis));
        que1.push(make_pair(tmp,0));
        pair<int,int>x,y;
            vis[tmp] = 1;
        while( !que1.empty())
        {
            x = que1.front();
            que1.pop();
            for(int i = 0; i < g[x.first].size() ; i++)
            {
                int v = g[x.first][i];
                if( vis[v] )continue;
                vis[v] = 1;
                que1.push(make_pair(v,x.second+1));
                res = res > x.second ? res : x.second + 1;
            }
        }
        return res;
    }
    int main()
    {
        int n,m,u,v;
        int i;
       // freopen("in.txt","r",stdin);
        while( ~scanf("%d%d",&n,&m) && n+m)
        {
            id = 0;
            memset(head,-1,sizeof(head));
            while( m-- )
            {
              scanf("%d%d",&u,&v);
              add_edge(u,v);
            }
            total = num = 0;
            memset(dfn,0,sizeof(dfn));
            memset(fa,-1,sizeof(fa));
            memset(vis,0,sizeof(vis));
            for(i = 1; i <= n; i++)//可以处理不连通的无向图,如果连通只需要一次即可
            {
                if( !dfn[i] )
                {
                    top = time = 1;
                    tarjan(i);
                  //num++;
                  //for( int j = 1; j <= n; j++) //特殊处理顶点的连通块
                  //    if( dfn[j] && fa[j] == -1)fa[j] = num;
                }
            }
            //for( i = 1; i <= n; i++)cout << fa[i] << endl;
            for(i = 1; i <= n;i++)g[i].clear();
            int x,y;
            //建树
           // cout << total << endl;
            for( i = 0 ; i < total; i++)
            {
                x = fa[bridge[i].u];
                y = fa[bridge[i].v];
               //cout << x << " " << y << endl;
                g[x].push_back(y);
                g[y].push_back(x);
            }
            memset(vis,0,sizeof(vis));
            ans = 0;
            dfs(1);
            printf("%d
    ",total - ans );
        }
        return 0;
    }
    

      

      

  • 相关阅读:
    String、StringBuffer、StringBuilder源码解读
    查询条件左边写入函数,导致无法命中索引
    【图形学手记】law of the unconscious statistician
    【图形学手记】蒙特卡洛方法相关笔记
    【图形学手记】抽样分布相关的数学笔记
    C++ lower_bound
    【图形学手记】Inverse Transform Sampling 逆转换抽样
    【Java学习笔记】LinkedList JDK1.6
    【疑难杂症】new Date() 造成的线程阻塞问题
    【疑难杂症】【Solved】maven-compiler-plugin 在 idea 下的问题
  • 原文地址:https://www.cnblogs.com/LUO257316/p/3221197.html
Copyright © 2011-2022 走看看