zoukankan      html  css  js  c++  java
  • Tarjan

    • 有向图G中,以顶点v为起点的弧的数目称为v的出度,记做deg+(v);以顶点v为终点的弧的数目称为v的入度,记做deg-(v)。
    • 如果在有向图G中,有一条<u,v>有向道路,则v称为u可达的,或者说,从u可达v。
    • 什么是强连通?强连通其实就是指图中有两点u,v。使得能够找到有向路径从u到v并且也能够找到有向路径从v到u,则称u,v是强连通的。
    • 如果有向图G的任意两个顶点都互相可达,则称图 G是强连通图,如果有向图G存在两顶点u和v使得u不能到v,或者v不能到u,则称图G是强非连通图。
    • 如果有向图G不是强连通图,他的子图G2是强连通图,点v属于G2,任意包含v的强连通子图也是G2的子图,则乘G2是有向图G的极大强连通子图,也称强连通分量。

    DFN【】记录遍历次序,low【】记录某环第一个被访问的点one,然后再第二次遍历到one的时候,将路径上所有的点的low【】全部更新为low【one】,也就是全部更新为第一次访问的点one;如果在回溯过程中DFN【X】 = low【X】,则说明存在一个强联通分量。

    Tarjan:可以用来缩点和找环,> 将一个有向带环图变成了一个有向无环图(DAG图) <

    【NOIP2015】信息传递

     数据规模与约定

    测试点编号nn 的规模
    1 n200n≤200
    2
    3
    4 n2500n≤2500
    5
    6
    7 n200000n≤200000
    8
    9
    10

    时间限制:1s

    空间限制:128MB

    #include <bits/stdc++.h>
    using namespace std;
    #define ll long long
    using namespace std;
    const int mod = 1e9+7;/// 998244353;
    const int mxn = 2e5 +7;
    int _,m,n,t,k,ans,cnt,lg;
    vector<int>e[mxn];
    stack<int>s;
    int vis[mxn] , dfn[mxn] , low[mxn] ;
    void tarjan(int x)
    {
        vis[x] = 1 ; s.push(x);
        low[x] = dfn[x] = cnt++;
        for(int i=0 , v ;i<e[x].size();i++){
            v = e[x][i] ;
            if(!dfn[v]){
                tarjan(v);
                low[x] = min( low[x] , low[v] );
            } else {
                low[x] = min( low[x] , dfn[v] );
            }
        }
        if(dfn[x]==low[x]){
            int res = 0 ;
            while(1){
                int now = s.top(); s.pop();
                vis[now] = 0 ;
                res++;
                if(now==x) break;
            }
            if(res>1) ans = min(res , ans ) ;
        }
    }
    void solve()
    {
        while(cin>>n)
        {
            cnt = 1 ; ans = mod ;
            for(int i=1;i<=n;i++){
                cin>>k;
                e[i].push_back(k);
            }
            for(int i=1;i<=n;i++){
                if(!vis[i]){
                    tarjan(i);
                }
            }
            cout<< ans <<endl;
        }
    }
    int main()
    {
        ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
        solve();
    }
    View Code

     HDU - 2586 How far away ?

    There are n houses in the village and some bidirectional roads connecting them. Every day peole always like to ask like this "How far is it if I want to go from house A to house B"? Usually it hard to answer. But luckily int this village the answer is always unique, since the roads are built in the way that there is a unique simple path("simple" means you can't visit a place twice) between every two houses. Yout task is to answer all these curious people.

    InputFirst line is a single integer T(T<=10), indicating the number of test cases. 
      For each test case,in the first line there are two numbers n(2<=n<=40000) and m (1<=m<=200),the number of houses and the number of queries. The following n-1 lines each consisting three numbers i,j,k, separated bu a single space, meaning that there is a road connecting house i and house j,with length k(0<k<=40000).The houses are labeled from 1 to n. 
      Next m lines each has distinct integers i and j, you areato answer the distance between house i and house j.OutputFor each test case,output m lines. Each line represents the answer of the query. Output a bland line after each test case.Sample Input

    2
    3 2
    1 2 10
    3 1 15
    1 2
    2 3
    
    2 2
    1 2 100
    1 2
    2 1

    Sample Output

    10
    25
    100
    100
    #include <bits/stdc++.h>
    using namespace std;
    #define ll long long
    using namespace std;
    const int mod = 1e9+7;/// 998244353;
    const int mxn = 5e4 +7;
    int _,m,n,t,k,ans,cnt,lg;
    struct e{
        int to,x,nx;
    }e[40000*2+7];
    int dep[mxn] , f[mxn][30] , len[mxn] , head[mxn] ;
    void add(int u,int v,int w)
    {
        e[cnt].to = v;
        e[cnt].x = w ;
        e[cnt].nx = head[u];
        head[u] = cnt++;
    }
    void bfs()
    {
        memset(f,0,sizeof(f));
        memset(dep,0.,sizeof(dep));
        queue<int>q;
        q.push(1);
        dep[1] = 1 ;
        while(!q.empty())
        {
            int u = q.front() ; q.pop() ;
            for(int i=head[u] ; ~i ;i = e[i].nx)
            {
                int v = e[i].to ;
                if(dep[v]) continue;
                len[v] = len[u] + e[i].x;
                dep[v] = dep[u] + 1 ;
                f[v][0] = u ; /// 存储父节点
                for(int j=1;j<=lg;j++)
                    f[v][j] = f[ f[v][j-1] ][j-1] ;
                q.push(v);
            }
        }
    }
    int lca(int u,int v)
    {
        if(dep[u]>dep[v] ) swap(u,v);
        for(int i=lg;i>=0;i--) /// 提升 V 和 U 至相同的高度
            if( dep[ f[v][i] ] >= dep[u] )
                v = f[v][i] ; 
        if(v==u) return u ;
        for(int i=lg;i>=0;i--) /// 找到最近的 LCA 
            if( f[u][i] != f[v][i] )
                u = f[u][i] , v = f[v][i] ;
        return f[u][0];
    }
    void solve()
    {
        for(cin>>t;t;t--)
        {
            cin>>n>>m;
            cnt = 0 ; lg = int(log(n)/log(2))+1; 
            memset(head,-1,sizeof(head));
            for(int i=1,u,v,w;i<n;i++){
                cin>>u>>v>>w;
                add(u,v,w);
                add(v,u,w);
            }
            bfs();
            while(m--)
            {
                int u , v ;
                cin>>u>>v;
                cout<<len[u]+len[v] - 2*len[ lca(u,v) ]<<endl;
            }
    
        }
    }
    int main()
    {
        ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
        solve();
    }
    View Code
    #include <bits/stdc++.h>
    using namespace std;
    #define ll long long
    using namespace std;
    const int mod = 1e9+7;/// 998244353;
    const int mxn = 8e4 +7;
    const int N = 8e4 + 7 ;
    int _,m,n,t,k,ans,cnt,lg;
    int head[N] , far[N] , len[N] , vis[N] , a[mxn] ;
    vector< pair<int,int> > q[N] ; 
    struct ${
        int to , nx , w ;    
    }e[mxn*2];
    int root(int x)
    {
        return x==far[x] ? x : far[x] = root(far[x]);
    }
    void add(int u,int v,int w)
    {
        e[cnt].to = v ;
        e[cnt].w = w ;
        e[cnt].nx = head[u] ;
        head[u] = cnt++;
    }
    void tarjan(int u)
    {
        vis[u] = 1 ;
        for(int i=head[u];~i;i=e[i].nx){
            int v = e[i].to ;
            if(!vis[v]){
                len[v] = len[u] + e[i].w ;
                tarjan(v);
                far[v] = u ;    
            }
        }
        for(int i=0;i<q[u].size();i++){
            int v = q[u][i].first , id = q[u][i].second ;
            if(vis[v]==2){
                int lca = root(v);
                a[id] = min( a[id] , len[u]+len[v] - 2*len[lca] );
            }
        }
        vis[u] = 2 ; 
    }
    void init()
    {
        cnt = 0 ;
        for(int i=0;i<=n;i++)
            len[i] = 0 , far[i] = i , vis[i] = 0;
        memset(head,-1,sizeof(head));
    }
    void solve()
    {
        for(cin>>t;t;t--){ 
            cin>>n>>m; 
            init();
            for(int i=1,u,v,w;i<n;i++){
                cin>>u>>v>>w;
                add(u,v,w);
                add(v,u,w);
            }
            for(int i=1,u,v;i<=m;i++){
                cin>>u>>v;
                q[u].push_back( {v,i} );
                q[v].push_back( {u,i} );
                a[i] = 1<<30 ;
            }
            tarjan(1);
            for(int i=1;i<=m;i++)
                cout<<a[i]<<endl;
        }
    }
    int main()
    {
        ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
        solve();
    }
    View Code
    所遇皆星河
  • 相关阅读:
    Selenium之IE浏览器的启动问题及解决
    Selenium之Chrome浏览器的启动问题及解决
    Selenium之IE浏览器的启动
    Selenium之firefox浏览器的启动
    【luogu 3373】【模板】线段树2
    【luogu 3372】【模板】线段树1
    【luogu 1908】逆序对
    【codevs2822】爱在心中
    【bzoj1051】 [HAOI2006]受欢迎的牛
    【luogu 2863】[USACO06JAN]牛的舞会The Cow Prom
  • 原文地址:https://www.cnblogs.com/Shallow-dream/p/13413412.html
Copyright © 2011-2022 走看看