最近遇到了这种模板题,记录一下
tarjan求桥,求割
1 #include <bits/stdc++.h>
2 using namespace std;
3 #define MOD 998244353
4 #define INF 0x3f3f3f3f3f3f3f3f
5 #define LL long long
6 #define MX 1005
7
8 int n, m, Ddex;
9 vector<int> G[MX];
10 int fat[MX];
11 int low[MX],dfn[MX];
12 bool is_cut[MX];
13
14 void Init()
15 {
16 Ddex=0;
17 for (int i=1;i<=n;i++) G[i].clear();
18 memset(dfn,-1,sizeof(dfn));
19 memset(fat,-1,sizeof(fat));
20 memset(is_cut,0,sizeof(is_cut));
21 }
22
23 void Tarjan(int i,int pre)
24 {
25 fat[i]=pre;
26 dfn[i]=low[i]=++Ddex;
27 for(int j=0;j<G[i].size();++j)
28 {
29 int k=G[i][j];
30 if(dfn[k]==-1)
31 {
32 Tarjan(k,i);
33 low[i]=min(low[i],low[k]);
34 }
35 else if(k!=pre) //假如k是i的父亲的话,那么这就是无向边中的重边,有重边那么一定不是桥*/
36 low[i]=min(low[i],dfn[k]);
37 }
38 }
39 void calc()
40 {
41 int rootson=0;
42 Tarjan(1,-1);
43 for(int i=2;i<=n;++i)
44 {
45 int v=fat[i];
46 if(v==1)
47 rootson++; //统计根节点子树的个数,根节点的子树个数>=2,就是割点
48 else{
49 if(low[i]>=dfn[v]) //割点的条件
50 is_cut[v]=true;
51 }
52 }
53 if(rootson>1)
54 is_cut[1]=true;
55 for(int i=1;i<=n;++i)
56 if(is_cut[i])
57 printf("%d
",i);
58
59 for(int i=1;i<=n;++i)
60 {
61 int v=fat[i];
62 if(v>0&&low[i]>dfn[v])//桥的条件
63 printf("%d, %d
",i,v);
64 }
65 }
66 int main()
67 {
68 while(scanf("%d%d",&n,&m)!=EOF)
69 {
70 Init();
71 int a,b;
72 for(int i=1;i<=m;++i)
73 {
74 scanf("%d%d",&a,&b);
75 G[a].push_back(b);
76 G[b].push_back(a);
77 }
78 calc();
79 }
80 return 0;
81 }
求强连通缩点加拓扑排序。。。