Tarjan相关(强连通分量,割点,缩点)

一、先上模板QWQ

#include<bits/stdc++.h>//tarjan-强连通分量 
using namespace std;
const int MAXM=100005;
const int MAXN=5005;
int n,m,tot,head[MAXN],dfn[MAXN],low[MAXN],cntt;
int colour[MAXN],cnt[MAXN],maxcnt,cntcol,sta[MAXN][MAXN];
bool vis[MAXN];
struct sth{
    int to,nxt;
}a[MAXM];
void add(int u,int v,int w){
    a[++tot].to=v;a[tot].nxt=head[u];
    head[u]=tot;
    if(w==2){a[++tot].to=u;
    a[tot].nxt=head[v];head[v]=tot;
    }
} 
stack<int>s;
int dfs(int x){
    dfn[x]=low[x]=++cntt;vis[x]=1;
    s.push(x);
    for(int j=head[x];j;j=a[j].nxt){
        int vv=a[j].to;
        if(!dfn[vv]){
            int lowv=dfs(vv);
            low[x]=min(low[x],lowv);
        }
        else{
            if(vis[vv]){
                low[x]=min(low[x],low[vv]); 
            }
        }
    }
    if(dfn[x]==low[x]){
        cntcol++;colour[x]=cntcol;cnt[cntcol]++;
        vis[x]=0;
        sta[cntcol][1]=x;
        while(s.top()!=x){
            colour[s.top()]=cntcol;cnt[cntcol]++;
            vis[s.top()]=0;sta[cntcol][cnt[cntcol]]=s.top();
            s.pop();
        }s.pop();
        maxcnt=max(maxcnt,cnt[cntcol]);
    }
    return low[x];
}
void tarjan(){
    for(int i=1;i<=n;i++){
        if(!dfn[i])dfs(i);
    }
}

int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        add(u,v,w);
    }
    tarjan();
    printf("%d\n",maxcnt);
    for(int i=1;i<=cntcol;i++){
        if(cnt[i]==maxcnt){
            sort(sta[i]+1,sta[i]+1+maxcnt);
            for(int j=1;j<=cnt[i];j++)printf("%d ",sta[i][j]);
            printf("\n");
            return 0;
        }
    }
}
#include<bits/stdc++.h>//tarjan 缩点 
using namespace std;
int n,m,tot,cnt,dep;
struct node{
    int to,nxt;
}a[200007];
int head[200005],dfn[200005],q[200005],low[200005],colour[200005];
bool vis[200005],use[200005];
stack<int>s;
int x[200005],y[200005];
int newq[200005],dp[200005];
void add(int u,int v){
    a[++tot].to=v;a[tot].nxt=head[u];
    head[u]=tot;
}
int tarjan(int u){
    dep++;vis[u]=1;
    s.push(u);
    int lowu=dep;dfn[u]=low[u]=dep;
    for(int j=head[u];j;j=a[j].nxt){
        int vv=a[j].to;
        if(!dfn[vv]){
            int lowv=tarjan(vv);
            lowu=min(lowu,lowv);
        }else{//huidao zuxian
            if(vis[vv])
            lowu=min(lowu,low[vv]);
        }
    }
    low[u]=lowu;
    if(low[u]==dfn[u]){//buneng huidao zhiqian
        cnt++;
        colour[u]=cnt;vis[u]=0;
        newq[cnt]+=q[u];
        while(s.top()!=u){
            colour[s.top()]=cnt;
            newq[cnt]+=q[s.top()];
            vis[s.top()]=0;
            s.pop();
        }s.pop();
    }
    return lowu;
}
void work(){
    for(int i=1;i<=n;i++){
        if(!dfn[i])tarjan(i);
    }
}
//void print(){
//  for(int i=1;i<=n;i++)printf("%d\n",colour[i]);
//}
void search(int u){
    if(dp[u])return;
    dp[u]=newq[u];
    int qwq=0;
    for(int j=head[u];j;j=a[j].nxt){
        int vv=a[j].to;
        if(!dp[vv])search(vv);
        qwq=max(qwq,dp[vv]);
    }dp[u]+=qwq;
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)scanf("%d",&q[i]);
    for(int i=1;i<=m;i++){
        scanf("%d%d",&x[i],&y[i]);
        add(x[i],y[i]);
    }work();
    //print();
    
    int ans=0;
    memset(head,0,sizeof head);
    memset(a,0,sizeof a);
    tot=0;
    for(int i=1;i<=m;i++)
        if(colour[x[i]]!=colour[y[i]])add(colour[x[i]],colour[y[i]]);
    for(int i=1;i<=cnt;i++){
        if(!dp[i]){
            search(i);
            ans=max(ans,dp[i]);
        }
    }
    printf("%d\n",ans);
    return 0;
}
#include<bits/stdc++.h>
using namespace std;
int n,m,tot,cnt,dep;
struct node{
    int to,nxt;
}a[200007];
int head[20005],dfn[20005],low[20005];
bool iscut[20005];
void add(int u,int v){
    a[++tot].to=v;a[tot].nxt=head[u];
    head[u]=tot;
}
void tarjan(int u,int fa){
    int ch=0;dep++;
    dfn[u]=low[u]=dep;
    for(int j=head[u];j;j=a[j].nxt){
        int vv=a[j].to;
        if(!dfn[vv]){
            ch++;//yiding shi erzi
            tarjan(vv,u);
            low[u]=min(low[u],low[vv]);
            if(low[vv]>=dfn[u])iscut[u]=1;//zhiyao you yige huibulai jiushi gedian 
        }else{//huidao zuxian
            if(vv!=fa&&dfn[vv]<dfn[u])
            low[u]=min(low[u],low[vv]);
        }
    }
    if(fa==-1&&ch==1)iscut[u]=0;
    if(fa==-1&&ch>=2)iscut[u]=1;
}
void work(){
    for(int i=1;i<=n;i++){
        if(!dfn[i])tarjan(i,-1);
    }
}
void print(){
    for(int i=1;i<=n;i++)
    if(iscut[i])cnt++;
    printf("%d\n",cnt);
    for(int i=1;i<=n;i++)
    if(iscut[i])printf("%d ",i);
}
int main(){
    scanf("%d%d",&n,&m);
    while(m--){
        int u,v;scanf("%d%d",&u,&v);
        add(u,v);add(v,u);
    }work();
    print();
    return 0;
}

二、几道例题

·洛谷 P1407 稳定婚姻

#include<bits/stdc++.h>
using namespace std;
const int MAXM=100007;
const int MAXN=10007;
struct sth{
    int to,nxt;
}a[MAXM];
map<string,int>G;
map<string,int>B;
int n,m,tot,head[MAXN];
void add(int u,int v){
    a[++tot].to=v;a[tot].nxt=head[u];
    head[u]=tot;
}
int dfn[MAXN],low[MAXN],colour[MAXN],cnt[MAXN],cntt,cntcol;
bool vis[MAXN];
stack<int>s;
void tarjan(int x){
    dfn[x]=low[x]=++cntt;vis[x]=1;
    s.push(x);
    for(int j=head[x];j;j=a[j].nxt){
        int vv=a[j].to;
        if(!dfn[vv]){
            tarjan(vv);
            low[x]=min(low[x],low[vv]);
        }
        else{
            if(vis[vv])low[x]=min(low[x],low[vv]);
        }
    }
    if(dfn[x]==low[x]){
        cntcol++;colour[x]=cntcol;
        cnt[cntcol]++;vis[x]=0;
        while(s.top()!=x){
            colour[s.top()]=cntcol;
            cnt[cntcol]++;vis[s.top()]=0;
            s.pop();
        }s.pop();
    }
}
void work(){
    for(int i=1;i<=n;i++){
        if(!dfn[i])tarjan(i);
    }
}
int main(){
    scanf("%d",&n);
    string a,b;
    for(int i=1;i<=n;i++){
        cin>>a>>b;
        G[a]=i;B[b]=i;
    }
    scanf("%d",&m);
    for(int i=1;i<=m;i++){
        cin>>a>>b;
        add(G[a],B[b]);
    }
    work();
    for(int i=1;i<=n;i++){
        if(cnt[colour[i]]>1)printf("Unsafe\n");
        else printf("Safe\n");
    }
    return 0;
}

·洛谷 P2746 [USACO5.3]校园网Network of Schools

//整张图强连通
//嘤嘤嘤 
#include<bits/stdc++.h>
using namespace std;
const int MAXN=105;
const int MAXM=10005;
struct sth{
    int to,nxt;
}a[MAXM];
int n,m,tot,head[MAXN];
void add(int u,int v){
    a[++tot].to=v;a[tot].nxt=head[u];
    head[u]=tot;
}
int dfn[MAXN],low[MAXN],cntt,colour[MAXN],cntcol,cnt[MAXN];
int ans1,ans2,cntr,cntc;
bool rudu[MAXN],chudu[MAXN],vis[MAXN];
stack<int>s;
int tarjan(int x){
    dfn[x]=low[x]=++cntt;vis[x]=1;s.push(x);
    for(int j=head[x];j;j=a[j].nxt){
        int vv=a[j].to;
        if(!dfn[vv]){
            int lowv=tarjan(vv);
            low[x]=min(low[x],lowv);
        }
        else{
            if(vis[vv]){
                low[x]=min(low[x],low[vv]);
            }
        }
    }
    if(dfn[x]==low[x]){
        cntcol++;colour[x]=cntcol;
        cnt[cntcol]++;vis[x]=0;
        while(s.top()!=x){
            colour[s.top()]=cntcol;
            cnt[cntcol]++;vis[s.top()]=0;
            s.pop();
        }s.pop();
    }
    return low[x];
}
void work(){
    for(int i=1;i<=n;i++){
        if(!dfn[i])tarjan(i);
    }
    //solve-A
    for(int i=1;i<=n;i++){
        for(int j=head[i];j;j=a[j].nxt){
            if(colour[i]==colour[a[j].to])continue;
            rudu[colour[a[j].to]]=1;
        }
    }
    for(int i=1;i<=cntcol;i++){
        if(!rudu[i])ans1++;
    }
    printf("%d\n",ans1);
    //solve-B
    cntr=ans1;
    for(int i=1;i<=n;i++){
        for(int j=head[i];j;j=a[j].nxt){
            if(colour[i]==colour[a[j].to])continue;
            chudu[colour[i]]=1;
        }
    }
    for(int i=1;i<=cntcol;i++){
        if(!chudu[i])cntc++;
    }
    ans2=max(cntr,cntc);
    if(cntcol==1)printf("0\n");
    else printf("%d\n",ans2);
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        int tmp;scanf("%d",&tmp);
        while(tmp){
            add(i,tmp);
            scanf("%d",&tmp);
        }
    }
    work();
    return 0;
}

·洛谷 P3469 [POI2008]BLO-Blockade

#include<bits/stdc++.h>
using namespace std;
const int MAXN=100007;
const int MAXM=1000007;
#define ll long long
ll ans[MAXN];
struct sth{
    ll to,nxt;
}a[MAXM];
ll n,m,tot,head[MAXN];
void add(ll u,ll v){
    a[++tot].to=v;a[tot].nxt=head[u];
    head[u]=tot;
}
ll dfn[MAXN],low[MAXN],cntt,size[MAXN];
bool vis[MAXN],iscut[MAXN];
void tarjan(ll x,ll fa){
    size[x]=1;
    ll sum=0;
    dfn[x]=low[x]=++cntt;
    ll ch=0;
    for(ll j=head[x];j;j=a[j].nxt){
        ll vv=a[j].to;
        if(!dfn[vv]){
            ch++;
            tarjan(vv,x);size[x]+=size[vv];
            low[x]=min(low[x],low[vv]);
            if(low[vv]>=dfn[x]){
                iscut[x]=1;sum+=size[vv];
                ans[x]+=size[vv]*(n-size[vv]);
            }
        }
        else{
            if(vv!=fa&&dfn[vv]<dfn[x]){
                low[x]=min(low[x],dfn[vv]);
            }
        }
    }
    if(fa==-1&&ch==1)iscut[x]=0;
    if(fa==-1&&ch>1)iscut[x]=1;
    if(!iscut[x])ans[x]=2*(n-1);
    else ans[x]+=(n-sum-1)*(sum+1)+(n-1);
}
void work(){
    for(ll i=1;i<=n;i++){
        if(!dfn[i])tarjan(i,-1);
    }
}
int main(){
    scanf("%lld%lld",&n,&m);
    for(ll i=1;i<=m;i++){
        ll u,v;
        scanf("%lld%lld",&u,&v);
        add(u,v);add(v,u);
    }
    work();
    for(ll i=1;i<=n;i++){
        printf("%lld\n",ans[i]);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/erutsiom/p/9905008.html