Tarjan algorithm designed to practice

1. maze castle

Question is intended: to FIG determines whether a strongly connected graph.

Solution: Tarjan number calculation using figures strongly connected component, and if one is strongly connected graph, otherwise not.

#include<bits/stdc++.h>

using namespace std;
const int N = 2e4+100;
typedef long long ll;
vector<int> G[N];
bool is_instack[N];
int dfn[N],low[N];
stack<int> sta;
int n,m,index,scc;
void init(){
    index=scc=0;
    memset(dfn,0,sizeof(dfn));
    memset(low,0,sizeof(low));
    memset(is_instack,0,sizeof(is_instack));
    while(!sta.empty()) sta.pop();
    for(int i=1;i<=n;i++) G[i].clear();
}
void Tarjan(int u){
    dfn[u]=low[u]=++index;
    sta.push(u);is_instack[u]=1;
    for(auto v:G[u]){
        if(!dfn[v]){
            Tarjan(v);
            low[u]=min(low[u],low[v]);
        }
        else if(is_instack[v]){
            low[u]=min(low[u],dfn[v]);
        }
    }
    if(low[u]==dfn[u]){
        ++scc;
        while(sta.top()!=u){
            is_instack[sta.top()]=0;
            sta.pop();
        }
    }
}
int main(){
    while(scanf("%d %d",&n,&m)){
        if(n+m==0) break;
        init();
        int u,v;
        for(int i=0;i<m;i++){
            scanf("%d %d",&u,&v);
            G[u].push_back(v);
        }
        for(int i=1;i<=n;i++){
            if(!dfn[i]) Tarjan(i);
        }
        if(scc==1) puts("Yes");
        else puts("No");
    }
    return 0;
}

2.Proving Equivalences

The meaning of problems: Given a directed graph, a minimum seek plus several directional edge such that the entire FIG become strongly connected.

Solution: After Tarjan condensing point calculating pronounced as \ (0 \) number \ (A \) and the degree of \ (0 \) number \ (B \) , takes a maximum value \ (max (a, B) \) , note that if you have a strongly connected graph, and the answer is \ (0 \) .

#include<bits/stdc++.h>

using namespace std;
const int N = 1e5+100;
vector<int> G[N],color[N];
stack<int> sta;
int dfn[N],low[N];
int id[N],od[N];
bool is_instack[N];
int scc[N],nscc,index;
int n,m;
void init(){
    nscc=index=0;
    memset(scc,0,sizeof(scc));
    memset(dfn,0,sizeof(dfn));
    memset(id,0,sizeof(id));
    memset(od,0,sizeof(od));
    memset(is_instack,0,sizeof(is_instack));
    memset(low,0,sizeof(low));
    for(int i=1;i<=n;i++) G[i].clear(),color[i].clear();
    while(!sta.empty()) sta.pop();
}
void Tarjan(int u){
    low[u]=dfn[u]=++index;
    sta.push(u);is_instack[u]=1;
    for(auto v:G[u]){
        if(!dfn[v]){
            Tarjan(v);
            low[u]=min(low[u],low[v]);
        }
        else if(is_instack[v]){
            low[u]=min(low[u],dfn[v]);
        }
    }
    if(low[u]==dfn[u]){
        ++nscc;
        while(1){
            int temp=sta.top();
            scc[temp]=nscc;
            sta.pop();
            is_instack[temp]=0;
            if(temp==u) break;
        }
    }
}
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d %d",&n,&m);
        init();
        int u,v;
        for(int i=1;i<=m;i++){
            scanf("%d %d",&u,&v);
            G[u].push_back(v);
        }
        for(int i=1;i<=n;i++){
            if(!dfn[i]) Tarjan(i);
        }
        //cerr<<nscc<<endl;
        if(nscc==1){
            puts("0");
        } 
        else{
            for(int i=1;i<=nscc;i++) id[i]=od[i]=1;
            for(int i=1;i<=n;i++){
                for(auto j:G[i]){
                    if(scc[i]!=scc[j]){
                        id[scc[j]]=od[scc[i]]=0;
                    }
                }
            } 
            int n1=0;int n2=0;
            for(int i=1;i<=nscc;i++){
                n1+=id[i];n2+=od[i];
            }
            printf("%d\n",max(n1,n2));
        }
    }
    return 0;
}

3.Summer Holiday

Meaning of the questions: to give you a, you need to choose a few points make use of these points can be traversed complete a directed graph, each point has a weight in this figure, but also meet the selection of these weights and minimum points.

Interpretations: Tarjan condensing point, and when the minimum reduction point of which the weight of strongly connected components shrunk point where the weights, and then look for the zero degree point number, namely the answer.
{% Fold click explicit / implicit content%}

#include<bits/stdc++.h>

using namespace std;
const int N = 1e5+100;
typedef long long ll;
const int INF = 0x3f3f3f3f;
int n,m,scc,index;
vector<int> G[N];
ll w[N],low[N],dfn[N],minn[N],color[N],id[N];
bool is_instack[N];stack<int> sta;
void init(){
    scc=index=0;
    memset(low,0,sizeof(low));
    memset(dfn,0,sizeof(dfn));
    memset(color,0,sizeof(color));
    memset(minn,INF,sizeof(minn));
    memset(is_instack,0,sizeof(is_instack));
    for(int i=1;i<=n;i++) G[i].clear();
    while(!sta.empty()) sta.pop();
}
void Tarjan(int u){
    low[u]=dfn[u]=++index;
    sta.push(u);is_instack[u]=1;
    for(auto v:G[u]){
        if(!dfn[v]){
            Tarjan(v);
            low[u]=min(low[u],low[v]);
        }
        else if(is_instack[v]){
            low[u]=min(low[u],dfn[v]);
        }
    }
    if(low[u]==dfn[u]){
        ++scc;
        while(1){
            int temp=sta.top();
            color[temp]=scc;
            minn[scc]=min(minn[scc],w[temp]);
            is_instack[temp]=0;
            sta.pop();
            if(temp==u) break;
        }
    }
}
int main(){
    while(scanf("%d %d",&n,&m)!=EOF){
        init();
        for(int i=1;i<=n;i++) scanf("%lld",&w[i]);
        int u,v;
        for(int i=1;i<=m;i++){
            scanf("%d %d",&u,&v);
            G[u].push_back(v);          
        }
        for(int i=1;i<=n;i++){
            if(!dfn[i]) Tarjan(i);
        }
        for(int i=1;i<=scc;i++) id[i]=1;
        for(int i=1;i<=n;i++){
            for(auto j:G[i]){
                if(color[i]!=color[j]){
                    id[color[j]]=0;
                }
            }
        }
        ll ans1,ans2;ans1=ans2=0;
        for(int i=1;i<=scc;i++){
            if(id[i]){
                ans1++;
                ans2+=minn[i];
            }
        }
        printf("%lld %lld\n",ans1,ans2);
    }
    return 0;
}

{%}% Endfold

4.Intelligence System

Meaning of the questions: a network of relationships, 0 contact on any one person, if two people can be direct or indirect contact with each other, then the two men's consumption of 0, 0 seek to contact the minimum consumption per person.

Interpretations: Tarjan condensing points, find the smallest tree, since the subject to ensure a solution, it is only necessary statistics for each edge point to the minimum weight. 0 strongly connected components where not considered.

#include<bits/stdc++.h>

using namespace std;
const int N = 50005 ;
typedef long long ll;
const ll INF = 0x3f3f3f3f;
ll low[N],dfn[N],minn[N],color[N];
bool  is_instack[N];
ll n,m,scc,index;
stack<ll> sta;
vector<pair<ll,ll> > G[N];
void init(){
    scc=index=0;
    for(int i=0;i<=n;i++){
        is_instack[i]=0;
        low[i]=0;
        dfn[i]=0;
        minn[i]=INF;
        G[i].clear();
    }
    while(!sta.empty()) sta.pop();
}
void Tarjan(ll u){
    low[u]=dfn[u]=++index;
    is_instack[u]=1;sta.push(u);
    for(auto V:G[u]){
        ll v=V.first;
        if(!dfn[v]){
            Tarjan(v);
            low[u]=min(low[u],low[v]);
        }
        else if(is_instack[v]){
            low[u]=min(low[u],dfn[v]);
        }
    }
    if(low[u]==dfn[u]){
        scc++;
        while(1){
            ll temp=sta.top();
            color[temp]=scc;
            is_instack[temp]=0;
            sta.pop();
            if(temp==u) break;
        }
    }
}
int main(){
    while(scanf("%lld %lld",&n,&m)!=EOF){
        map<pair<ll,ll>,ll> WW;
        //pair<ll,ll> pnow;
        init();
        ll u,v,w;
        for(ll i=1;i<=m;i++){
            scanf("%lld %lld %lld",&u,&v,&w);
            //pnow.first=u;pnow.second=v;
            //if(!WW[pnow]) WW[pnow]=w;
            //else WW[pnow]=min(WW[pnow],w);
            G[u].push_back(make_pair(v,w));
        }
        long long ans=0;
        for(ll i=0;i<n;i++){
            if(!dfn[i]) Tarjan(i);
        }
        for(ll i=0;i<n;i++){
            for(auto j:G[i]){
                ll x=color[i];
                ll y=color[j.first];
                if(x!=y) minn[y]=min(minn[y],(ll)j.second);
            }
        }
        for(ll i=1;i<=scc;i++){
            if(i!=color[0]) ans+=minn[i];
        }
        printf("%lld\n",ans);
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/codancer/p/12232291.html