zoukankan      html  css  js  c++  java
  • Tarjan专题

    前排Orz tarjan

    tarjan算法在图的连通性方面有非常多的应用,dfn和low数组真是奥妙重重(并没有很搞懂反正背就完事了)

    有向图强连通分量

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<cmath>
     5 #include<stack>
     6 using namespace std;
     7 struct edge{
     8     int v,next;
     9 }a[100001];
    10 stack<int>s;
    11 int n,m,u,v,sum=0,tt=-1,ans=0,h[100001],anss[100001],num[100001],nums[100001],tot=0,tim=0,dfn[100001],low[100001],head[100001];
    12 bool used[100001],isin[100001];
    13 void tarjan(int u){
    14     int v;
    15     used[u]=isin[u]=true;
    16     low[u]=dfn[u]=++tim;
    17     s.push(u);
    18     for(int tmp=head[u];tmp!=-1;tmp=a[tmp].next){
    19         v=a[tmp].v;
    20         if(!used[v]){
    21             tarjan(v);
    22             low[u]=min(low[u],low[v]);
    23         }else{
    24             if(isin[v])low[u]=min(low[u],dfn[v]);
    25         }
    26     }
    27     if(low[u]==dfn[u]){
    28         v=-1;
    29         sum++;
    30         while(v!=u){
    31             v=s.top();
    32             s.pop();
    33             isin[v]=0;
    34             num[v]=sum;
    35             nums[sum]++;
    36         }
    37     }
    38 }
    39 void add(int u,int v){
    40     a[++tot].v=v;
    41     a[tot].next=head[u];
    42     head[u]=tot;
    43 }
    44 int main(){
    45     memset(used,0,sizeof(used));
    46     memset(head,-1,sizeof(head));
    47     memset(h,-1,sizeof(h));
    48     scanf("%d%d",&n,&m);
    49     for(int i=1;i<=m;i++){
    50         scanf("%d%d",&u,&v);
    51         add(u,v);
    52     }
    53     for(int i=1;i<=n;i++){
    54         if(!used[i])tarjan(i);
    55     }
    56     tot=0;
    57     for(int i=1;i<=n;i++){
    58         for(int tmp=head[i];tmp!=-1;tmp=a[tmp].next){
    59             if(num[i]!=num[a[tmp].v]){
    60                 h[num[i]]=++tot;
    61             }
    62         }
    63     }
    64     for(int i=1;i<=sum;i++){
    65         if(nums[i]>1)ans++;
    66     }
    67     printf("%d
    ",ans);
    68     for(int i=1;i<=sum;i++){
    69         if(h[i]==-1){
    70              if(tt!=-1||nums[i]==1){
    71                 tt=-1;
    72                 break;
    73              }else tt=i;
    74         }
    75     }
    76     if(tt==-1)printf("-1");
    77     else for(int i=1;i<=n;i++){
    78         if(num[i]==tt)printf("%d ",i);
    79     }
    80     return 0;
    81 }

    无向图割点

      1 #include<iostream>
      2 #include<cstring>
      3 #include<cstdio>
      4 #include<cmath>
      5 using namespace std;
      6 struct edge{
      7     int v,next;
      8 }a[100001];
      9 int t=0,n,s,ss,u,v,tim=0,sum=0,tot=0,head[100001],dfn[100001],low[100001];
     10 bool f=false,used[100001],ff[100001];
     11 void add(int u,int v){
     12     a[++tot].v=v;
     13     a[tot].next=head[u];
     14     head[u]=tot;
     15 }
     16 void tarjan(int u,int fa){
     17     int v;
     18     dfn[u]=low[u]=++tim;
     19     for(int tmp=head[u];tmp!=-1;tmp=a[tmp].next){
     20         v=a[tmp].v;
     21         if(!low[v]){
     22             tarjan(v,u);
     23             if(u==1)sum++;
     24             low[u]=min(low[u],low[v]);
     25             if(u!=1&&dfn[u]<=low[v]){
     26                 ff[u]=true;
     27             }
     28         }else if(v!=fa){
     29             low[u]=min(low[u],dfn[v]);
     30         }
     31     }
     32 }
     33 void dfs(int u){
     34     int v;
     35     used[u]=true;
     36     for(int tmp=head[u];tmp!=-1;tmp=a[tmp].next){
     37         v=a[tmp].v;
     38         if(!used[v])dfs(v);
     39     }
     40 }
     41 int main(){
     42     while(scanf("%d",&s)&&s){
     43         printf("Network #%d
    ",++t);
     44         memset(head,-1,sizeof(head));
     45         memset(ff,0,sizeof(ff));
     46         memset(dfn,0,sizeof(dfn));
     47         memset(low,0,sizeof(low));
     48         tot=n=sum=tim=0;
     49         f=false;
     50         scanf("%d",&ss);
     51         add(s,ss);
     52         add(ss,s);
     53         n=max(n,max(s,ss));
     54         scanf("%d",&s);
     55         while(s){
     56             scanf("%d",&ss);
     57             add(s,ss);
     58             add(ss,s);
     59             n=max(n,max(s,ss));
     60             scanf("%d",&s);
     61         }
     62         tarjan(1,-1);
     63         if(sum>1)ff[1]=true;
     64         for(int i=1;i<=n;i++){
     65             if(ff[i]){
     66                 memset(used,0,sizeof(used));
     67                 f=used[i]=true;
     68                 sum=0;
     69                 for(int j=1;j<=n;j++){
     70                     if(!used[j]){
     71                         sum++;
     72                         dfs(j);
     73                     }
     74                 }
     75                 printf("  SPF node %d leaves %d subnets
    ",i,sum);  
     76             }
     77         }
     78         if(!f){
     79             printf("  No SPF nodes
    ");
     80         }
     81         printf("
    ");
     82     }
     83     return 0;
     84 }
     85 /*
     86 1 2
     87 5 4
     88 3 1
     89 3 2
     90 3 4
     91 3 5
     92 0
     93 
     94 1 2
     95 2 3
     96 3 4
     97 4 5
     98 5 1
     99 0
    100 
    101 1 2
    102 2 3
    103 3 4
    104 4 6
    105 6 3
    106 2 5
    107 5 1
    108 0
    109 
    110 0
    111 --------
    112 Network #1
    113   SPF node 3 leaves 2 subnets
    114 
    115 Network #2
    116   No SPF nodes
    117 
    118 Network #3
    119   SPF node 2 leaves 2 subnets
    120   SPF node 3 leaves 2 subnets
    121 */

    无向图点双连通分量

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<vector>
     5 #include<cmath>
     6 #include<stack>
     7 using namespace std;
     8 struct edge{
     9     int v,next;
    10 }a[200001];
    11 struct edge1{
    12     int u,v;
    13 };
    14 int n,m,u,v,tot=0,tim=0,bcctot=0,bccnum[100001],head[100001],dfn[100001],low[100001],iscut[100001];
    15 vector<int>ans[100001];
    16 stack<edge1>s;
    17 void add(int u,int v){
    18     a[++tot].v=v;
    19     a[tot].next=head[u];
    20     head[u]=tot;
    21 }
    22 void tarjan(int u,int fa){
    23     edge1 t;
    24     int v,son;
    25     dfn[u]=low[u]=++tim;
    26     for(int tmp=head[u];tmp!=-1;tmp=a[tmp].next){
    27         v=a[tmp].v;
    28         if(v==fa)continue;
    29         t.u=u;
    30         t.v=v;
    31         if(!dfn[v]){
    32             s.push(t);
    33             son++;
    34             tarjan(v,u);
    35             low[u]=min(low[u],low[v]);
    36             if(low[v]>=dfn[u]){
    37                 iscut[u]=true;
    38                 ans[++bcctot].clear();
    39                 while(true){
    40                     edge1 tt=s.top();
    41                     s.pop();
    42                     if(bccnum[tt.u]!=bcctot){
    43                         ans[bcctot].push_back(tt.u);
    44                         bccnum[tt.u]=bcctot;
    45                     }
    46                     if(bccnum[tt.v]!=bcctot){
    47                         ans[bcctot].push_back(tt.v);
    48                         bccnum[tt.v]=bcctot;
    49                     }
    50                     if(tt.u==u&&tt.v==v)break;
    51                 }
    52             }
    53         }else if(dfn[v]<low[u]){
    54             s.push(t);
    55             low[u]=min(low[u],dfn[v]);
    56         }
    57     }
    58     if(fa<0&&son==1)iscut[u]=false;
    59 }
    60 int main(){
    61     memset(iscut,0,sizeof(iscut));
    62     memset(head,-1,sizeof(head));
    63     memset(low,0,sizeof(low));
    64     memset(bccnum,0,sizeof(bccnum));
    65     scanf("%d%d",&n,&m);
    66     for(int i=1;i<=m;i++){
    67         scanf("%d%d",&u,&v);
    68         add(u,v);
    69         add(v,u);
    70     }
    71     tarjan(1,-1);
    72     for(int i=1;i<=bcctot;i++){
    73         printf("%d:",i);
    74         for(int j=0;j<ans[i].size();j++){
    75             printf("%d ",ans[i][j]);
    76         }
    77         printf("
    ");
    78     }
    79     return 0;
    80 }
    81 /*
    82 6 7 
    83 1 2 
    84 2 3 
    85 1 3 
    86 3 4 
    87 4 5 
    88 3 5 
    89 5 6 
    90 --------
    91 1:5 6
    92 2:4 3 5
    93 3:2 1 3
    94 */

    无向图求桥

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<cmath>
     5 using namespace std;
     6 struct edge{
     7     int u,v,next;
     8 }a[100001];
     9 int n,m,u,v,tot=0,tim=0,head[100001],dfn[100001],low[100001],ansu[100001],ansv[100001];
    10 void add(int u,int v){
    11     a[++tot].u=u;
    12     a[tot].v=v;
    13     a[tot].next=head[u];
    14     head[u]=tot;
    15 }
    16 void tarjan(int u,int fa){
    17     int v;
    18     dfn[u]=low[u]=++tim;
    19     for(int tmp=head[u];tmp!=-1;tmp=a[tmp].next){
    20         v=a[tmp].v;
    21         if(dfn[v]==0){
    22             tarjan(v,u);
    23             low[u]=min(low[u],low[v]);
    24             if(low[v]>dfn[u]){
    25                 ansu[++ansu[0]]=u;
    26                 ansv[++ansv[0]]=v;
    27             }
    28         }else{
    29             if(dfn[v]<dfn[u]&&v!=fa){
    30                 low[u]=min(low[u],dfn[v]);
    31             }
    32         }
    33     }
    34 }
    35 int main(){
    36     memset(head,-1,sizeof(head));
    37     memset(dfn,0,sizeof(dfn));
    38     memset(low,0,sizeof(low));
    39     ansu[0]=0;
    40     ansv[0]=0;
    41     scanf("%d%d",&n,&m);
    42     for(int i=1;i<=m;i++){
    43         scanf("%d%d",&u,&v);
    44         add(u,v);
    45         add(v,u);
    46     }
    47     tarjan(1,-1);
    48     printf("--------
    ");
    49     for(int i=1;i<=ansv[0];i++){
    50         printf("%d %d
    ",ansu[i],ansv[i]);
    51     }
    52     return 0;
    53 }
    54 /*
    55 6 7
    56 1 2
    57 2 3
    58 1 3
    59 3 4
    60 4 5
    61 5 6
    62 6 4
    63 --------
    64 3 4
    65 */

    无向图边双连通分量

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<vector>
     5 #include<cmath>
     6 using namespace std;
     7 struct edge{
     8     int v,next;
     9 }a[100001];
    10 int n,m,u,v,tot=0,tim=0,num=0,head[100001],dfn[100001],low[100001],bl[100001];
    11 bool used[100001],bri[100001];
    12 vector<int>g[100001];
    13 void add(int u,int v){
    14     a[++tot].v=v;
    15     a[tot].next=head[u];
    16     head[u]=tot;
    17 }
    18 void tarjan(int u,int fa){
    19     int v;
    20     dfn[u]=low[u]=++tim;
    21     for(int tmp=head[u];tmp!=-1;tmp=a[tmp].next){
    22         v=a[tmp].v;
    23         if(dfn[v]==0){
    24             tarjan(v,u);
    25             low[u]=min(low[u],low[v]);
    26             if(low[v]>dfn[u]){
    27                 bri[tmp]=true;
    28                 bri[tmp^1]=true;
    29             }
    30         }else{
    31             if(dfn[v]<dfn[u]&&v!=fa){
    32                 low[u]=min(low[u],dfn[v]);
    33             }
    34         }
    35     }
    36 }
    37 void dfs(int u){
    38     used[u]=true;
    39     bl[u]=num;
    40     g[num].push_back(u);
    41     for(int tmp=head[u];tmp!=-1;tmp=a[tmp].next){
    42         int v=a[tmp].v;
    43         if(bri[tmp])continue;
    44         if(!used[v])dfs(v);
    45     }
    46 }
    47 int main(){
    48     memset(head,-1,sizeof(head));
    49     memset(dfn,0,sizeof(dfn));
    50     memset(low,0,sizeof(low));
    51     memset(used,0,sizeof(used));
    52     memset(bri,0,sizeof(bri));
    53     memset(bl,0,sizeof(bl));
    54     scanf("%d%d",&n,&m);
    55     for(int i=1;i<=m;i++){
    56         scanf("%d%d",&u,&v);
    57         add(u,v);
    58         add(v,u);
    59     }
    60     for(int i=1;i<=n;i++){
    61         if(!dfn[i])tarjan(i,-1);
    62     }
    63     for(int i=1;i<=n;i++){
    64         if(!used[i]){
    65             num++;
    66             dfs(i);
    67         }
    68     }
    69     for(int i=1;i<=num;i++){
    70         printf("%d: ",i);
    71         for(int j=0;j<g[i].size();j++)printf("%d ",g[i][j]);
    72         printf("
    ");
    73     }
    74     return 0;
    75 }
  • 相关阅读:
    Linux安装cx_Oracle
    LVM分区
    命令行重启远程桌面服务
    常用Linux命令
    自动清理N天前的二进制日志
    MySQL常用操作
    Java里的堆(heap)栈(stack)和方法区(method)
    SpringMVC 八大注解
    Spring Cloud原理详解
    java线程的生命周期及五种基本状态
  • 原文地址:https://www.cnblogs.com/dcdcbigbig/p/8946774.html
Copyright © 2011-2022 走看看