zoukankan      html  css  js  c++  java
  • tarjan模板

    tarjan

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cmath>
     4 #include <cstring>
     5 #include <string>
     6 #include <algorithm>
     7 #include <set>
     8 #include <map>
     9 #include <queue>
    10 #include <iostream>
    11 using namespace std;
    12 
    13 #define ll long long
    14 
    15 const int maxn=1e4+10;
    16 const int inf=1e9;
    17 const double eps=1e-8;
    18 
    19 struct node
    20 {
    21     int d;
    22     node *to;
    23 }*e[maxn];
    24 
    25 int id,dfn[maxn],low[maxn],tot_st,st[maxn],m,group[maxn];
    26 bool vis[maxn],vis_st[maxn];
    27 
    28 /**
    29 id:编号 每增加一个点,++id
    30 每增加一个点,加入栈中
    31 low:点的编号
    32 dfn:点以及后续点通过一条边能到的最小编号点的编号
    33 
    34 同一个类 dfn[d]=low[d] 栈中,第x个数d到栈顶 任意点的low值为dfn[d]
    35 st:栈 若点变为在一个类中时,从栈中弹出
    36 vis_st : 当点还未标记到类中时,可以使用
    37 
    38 m:类的个数
    39 group:每个点所在的类
    40 **/
    41 
    42 void tarjan(int d)
    43 {
    44     int dd;
    45     vis[d]=1;
    46     dfn[d]=low[d]=++id;
    47     st[++tot_st]=d;
    48     node *p=e[d];
    49     while (p)
    50     {
    51         dd=p->d;
    52         if (!vis[dd])
    53         {
    54             tarjan(dd);
    55             low[d]=min(low[d],low[dd]);
    56         }
    57         else if (!vis_st[dd])
    58             low[d]=min(low[d],dfn[dd]);
    59         p=p->to;
    60     }
    61     if (dfn[d]==low[d])
    62     {
    63         m++;
    64         int g=tot_st;
    65         while (st[tot_st]!=d)
    66         {
    67             group[st[tot_st]]=m;
    68             vis_st[st[tot_st]]=1;
    69             tot_st--;
    70         }
    71         group[st[tot_st]]=m;
    72         vis_st[st[tot_st]]=1;
    73         tot_st--;
    74         g-=tot_st;  ///类的大小
    75     }
    76 }
    77 
    78 int main()
    79 {
    80     node *p;
    81     int n,q,x,y,i;
    82     scanf("%d%d",&n,&q);
    83     while (q--)
    84     {
    85         scanf("%d%d",&x,&y);
    86         ///注意单边还是双边
    87         p=new node();
    88         p->d=y;
    89         p->to=e[x];
    90         e[x]=p;
    91     }
    92     for (i=1;i<=n;i++)
    93         if (!vis[i])
    94             tarjan(i);
    95     return 0;
    96 }
    97 /*
    98 
    99 */

    luogu P1726 上白泽慧音

      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <cmath>
      4 #include <cstring>
      5 #include <string>
      6 #include <algorithm>
      7 #include <set>
      8 #include <map>
      9 #include <queue>
     10 #include <iostream>
     11 using namespace std;
     12 
     13 #define ll long long
     14 
     15 const int maxn=1e4+10;
     16 const int inf=1e9;
     17 const double eps=1e-8;
     18 
     19 struct node
     20 {
     21     int d;
     22     node *to;
     23 }*e[maxn];
     24 
     25 int id,dfn[maxn],low[maxn],tot_st,st[maxn],m,group[maxn]; ///m:类的个数
     26 bool vis[maxn],vis_st[maxn];    ///st:栈,存储未被'类‘标签的点
     27 
     28 int ind,maxg=0,md;
     29 
     30 void tarjan(int d)
     31 {
     32     int dd;
     33     vis[d]=1;
     34     dfn[d]=low[d]=++id;
     35     st[++tot_st]=d;
     36     node *p=e[d];
     37     while (p)
     38     {
     39         dd=p->d;
     40         if (!vis[dd])
     41         {
     42             tarjan(dd);
     43             low[d]=min(low[d],low[dd]);
     44         }
     45         else if (!vis_st[dd])
     46             low[d]=min(low[d],dfn[dd]);
     47         p=p->to;
     48     }
     49     if (dfn[d]==low[d])
     50     {
     51         m++;
     52         int g=tot_st,mind=inf;
     53         while (st[tot_st]!=d)
     54         {
     55             group[st[tot_st]]=m;
     56             mind=min(mind,st[tot_st]);
     57             vis_st[st[tot_st]]=1;
     58             tot_st--;
     59         }
     60         group[st[tot_st]]=m;
     61         mind=min(mind,st[tot_st]);
     62         vis_st[st[tot_st]]=1;
     63         tot_st--;
     64         g-=tot_st;
     65         if (maxg<g || (maxg==g && mind<md))
     66             ind=m,maxg=g,md=mind;
     67     }
     68 }
     69 
     70 int main()
     71 {
     72     node *p;
     73     int n,q,x,y,z,i;
     74     scanf("%d%d",&n,&q);
     75     while (q--)
     76     {
     77         scanf("%d%d%d",&x,&y,&z);
     78         p=new node();
     79         p->d=y;
     80         p->to=e[x];
     81         e[x]=p;
     82         if (z==2)
     83         {
     84             p=new node();
     85             p->d=x;
     86             p->to=e[y];
     87             e[y]=p;
     88         }
     89     }
     90     for (i=1;i<=n;i++)
     91         if (!vis[i])
     92             tarjan(i);
     93     printf("%d",maxg);
     94     bool v=0;
     95     for (i=1;i<=n;i++)
     96         if (group[i]==ind)
     97         {
     98             if (!v)
     99                 printf("
    "),v=1;
    100             else
    101                 printf(" ");
    102             printf("%d",i);
    103         }
    104     return 0;
    105 }
    106 /*
    107 
    108 */

    luogu P3387 【模板】缩点

      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <cmath>
      4 #include <cstring>
      5 #include <string>
      6 #include <algorithm>
      7 #include <set>
      8 #include <map>
      9 #include <queue>
     10 #include <iostream>
     11 using namespace std;
     12 
     13 #define ll long long
     14 
     15 const int maxn=1e4+10;
     16 const int inf=1e9;
     17 const double eps=1e-8;
     18 
     19 /*
     20 题目描述
     21 给定一个n个点m条边有向图,每个点有一个权值,求一条路径,使路径经过的点权值之和最大。你只需要求出这个权值和。
     22 允许多次经过一条边或者一个点,但是,重复经过的点,权值只计算一次。
     23 
     24 第一行,n,m
     25 第二行,n个整数,依次代表点权
     26 第三至m+2行,每行两个整数u,v,表示u->v有一条有向边
     27 
     28 共一行,最大的点权之和。
     29 
     30 2 2
     31 1 1
     32 1 2
     33 2 1
     34 
     35 2
     36 */
     37 
     38 struct node
     39 {
     40     int d;
     41     node *to;
     42 }*e[maxn],*gr[maxn];
     43 
     44 int id,dfn[maxn],low[maxn],tot_st,st[maxn],m,group[maxn];
     45 bool vis[maxn],vis_st[maxn];
     46 int v[maxn],ans[maxn];///
     47 
     48 /**
     49 id:编号 每增加一个点,++id
     50 每增加一个点,加入栈中
     51 low:点的编号
     52 dfn:点以及后续点通过一条边能到的最小编号点的编号
     53 
     54 同一个类 dfn[d]=low[d] 栈中,第x个数d到栈顶 任意点的low值为dfn[d]
     55 st:栈 若点变为在一个类中时,从栈中弹出
     56 vis_st : 当点还未标记到类中时,可以使用
     57 
     58 m:类的个数
     59 group:每个点所在的类
     60 **/
     61 
     62 void tarjan(int d)
     63 {
     64     int dd;
     65     vis[d]=1;
     66     dfn[d]=low[d]=++id;
     67     st[++tot_st]=d;
     68     node *p=e[d];
     69     while (p)
     70     {
     71         dd=p->d;
     72         if (!vis[dd])
     73         {
     74             tarjan(dd);
     75             low[d]=min(low[d],low[dd]);
     76         }
     77         else if (!vis_st[dd])
     78             low[d]=min(low[d],dfn[dd]);
     79         p=p->to;
     80     }
     81     if (dfn[d]==low[d])
     82     {
     83         m++;
     84         while (st[tot_st]!=d)
     85         {
     86             group[st[tot_st]]=m;    ///
     87             vis_st[st[tot_st]]=1;
     88             tot_st--;
     89         }
     90         group[st[tot_st]]=m;    ///
     91         vis_st[st[tot_st]]=1;
     92         tot_st--;
     93     }
     94 }
     95 
     96 void dfs(int d)
     97 {
     98     node *p=gr[d];
     99     int dd,add=0;
    100     vis[d]=1;
    101     while (p)
    102     {
    103         dd=p->d;
    104         if (!vis[dd])
    105             dfs(dd);
    106         add=max(add,ans[dd]); ///点d到达下一个点,最大的值 千万注意这个是放在外面的
    107         p=p->to;
    108     }
    109     ans[d]+=add;
    110 }
    111 
    112 int main()
    113 {
    114     node *p,*r;
    115     int n,q,x,y,i,d;
    116     scanf("%d%d",&n,&q);
    117 
    118     for (i=1;i<=n;i++)  ///点权
    119         scanf("%d",&v[i]);
    120 
    121     while (q--)
    122     {
    123         scanf("%d%d",&x,&y);
    124         ///注意单边还是双边
    125         p=new node();
    126         p->d=y;
    127         p->to=e[x];
    128         e[x]=p;
    129     }
    130     for (i=1;i<=n;i++)
    131         if (!vis[i])
    132             tarjan(i);
    133 
    134     for (i=1;i<=n;i++)
    135     {
    136         ans[group[i]]+=v[i];    ///同一类,能互相访问所有的点
    137         p=e[i];
    138         while (p)
    139         {
    140             d=p->d;
    141             if (group[i]!=group[d])
    142             {
    143                 r=new node();   ///变量名要有区分
    144                 r->d=group[d];
    145                 r->to=gr[group[i]];
    146                 gr[group[i]]=r;
    147 
    148 //                printf("%d %d
    ",group[i],group[d]);
    149             }
    150             p=p->to;
    151         }
    152     }
    153 
    154     ///tarjan+缩点后无环
    155     memset(vis,0,sizeof(vis));
    156     for (i=1;i<=n;i++)
    157         if (!vis[i])
    158             dfs(i);
    159     int maxa=0;
    160     for (i=1;i<=n;i++)
    161         maxa=max(maxa,ans[i]);
    162     printf("%d",maxa);
    163     return 0;
    164 }
    165 /*
    166 3 2
    167 1 2 3
    168 1 2
    169 1 3
    170 */

    luogu P3388 【模板】割点(割顶)

  • 相关阅读:
    java 如何判断邮箱是否正确
    Android SDK Manager无法更新的解决
    洛谷P1162
    真 随笔
    初始化结构体
    Linux mkdir -p 后出现permission denied问题
    校赛F
    HDU1022
    UVa156
    HDU1060
  • 原文地址:https://www.cnblogs.com/cmyg/p/10746998.html
Copyright © 2011-2022 走看看