• CodeForces


    CF1000E We Need More Bosses

    题目大意:

    n点m边无向图,找到两个点s、t,使得s到t必须经过的边最多,求最多的必须经过边数。

    思路:

    题目关键在于对“必须经过的边”的理解,拿样例1来说

    5 5					5
    1 2					|
    2 3					2
    3 1				       / 
    4 1				      3---1
    5 2					  |
    					  4
    

    在同一个双连通分量中,任意两点都至少有两条简单路径,所以一个双连通分量内的点都不是必须经过的边,自然想到使用tarjan缩点,缩点后得到的无向图无环而形成了一棵树,我们使用两次dfs求得树上直径即可得到答案。

    Code:
    #include <bits/stdc++.h>
    using namespace std;
    const int N = 300010;
    // const int N = 10;
    
    int dfn[N], low[N], co[N]/*缩点后每个点对应的标号*/, col/*缩点后还有几个点*/, num/*时间戳*/;
    int st[N], top;
    bool vis[N];
    
    vector<int> G[N << 1], G2[N << 1];
    int n, m;
    int maxdis, maxv;
    
    int min(int a, int b) { return a < b ? a : b; }
    
    void tarjan(int x, int fa) {
        dfn[x] = low[x] = ++num;
        st[++top] = x;
        vis[x] = 1;
        for (int i = 0; i < G[x].size(); i++) {
            int v = G[x][i];
            if (v == fa) continue;
            if (!dfn[v]) { //没访问过
                tarjan(v, x);
                low[x] = min(low[x], low[v]);
            } else if (vis[v]) { //在栈中
                low[x] = min(low[x], dfn[v]);
            }
        }
        if (low[x] == dfn[x]) { //防止一个环遍历到一半就出栈了
            col++;
            while (1) {
                co[st[top]] = col;
                // printf("%d ", st[top]);
                vis[st[top]] = 0;
                if (st[top--] == x) break;
            }
            //printf ("
    ") ;
        }
    }
    
    //u:dfs的源点,f: u点的父节点,d2s:u点到源点的距离
    void dfs(int u, int f, int d2s) {
    	if (maxdis < d2s){
    		maxdis = d2s;
    		maxv = u;
    	}
            for (int i = 0; i < G2[u].size(); i++) {
                int v = G2[u][i];
                if (v == f) continue;
                dfs(v, u ,d2s + 1);
            }
    }
    
    int main() {
        ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
        cin >> n >> m;
        for (int i = 0; i < m; i++) {
            int u, v; cin >> u >> v;
            G[u].push_back(v);
            G[v].push_back(u);
        }
        tarjan(1, 0);
        for (int i = 1; i <= n; i++) { //缩点后遍历原图重新建图为G2
            for (int j = 0; j < G[i].size(); j++) {
                int v = G[i][j];
                if (co[i] != co[v]) { //省去同一个环内的点的连边
                    G2[co[i]].push_back(co[v]);
                }
            }
        }
        //在缩点后的树上求最长距离
        dfs(1, -1, 0);
        maxdis = 0;
        dfs(maxv, -1, 0);
        cout << maxdis << endl;
        return 0;
    }
    
  • 相关阅读:
    HTTP 常用 Header
    三大框架面试笔记-Hibernate
    三大框架面试笔记-Spring
    Bloom Filter概念和原理
    笔记:编写高质量代码 改善Java程序的151个建议
    笔记:Effective Java
    HTTP状态码
    JAVA8 十大新特性详解
    java7 新特性
    笔记:Hadoop权威指南 第10章 管理Hadoop
  • 原文地址:https://www.cnblogs.com/Nepenthe8/p/14313617.html
Copyright © 2020-2023  润新知