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("\n"),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\n",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 【模板】割点(割顶)

 

posted @ 2019-04-21 21:16  congmingyige  阅读(241)  评论(0编辑  收藏  举报