题目大意:
给一个有向图
求一个最大的强连通分量,输出这个强连通分量里的所有元素
若两个联通分量内点数相同 则输出字典序小的那个
思路:
直接tarjan
对每个连通分量,求一下最小点,然后判断字典序就行了
1 #include<iostream>
2 #include<cstdio>
3 #include<algorithm>
4 #include<cmath>
5 #include<cstring>
6 #include<cstdlib>
7 #include<set>
8 #include<map>
9 #include<vector>
10 #include<stack>
11 #include<queue>
12 #define ll long long
13 #define inf 2147383611
14 #define MAXN 100100
15 #define MOD 5050
16 using namespace std;
17 inline int read()
18 {
19 int x=0,f=1;
20 char ch;ch=getchar();
21 while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
22 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
23 return x*f;
24 }
25 int n,m,next[MAXN*2],first[MAXN],to[MAXN*2],cnt;
26 int scc,dfn[MAXN],low[MAXN],bl[MAXN],stp,num[MAXN],minn[MAXN];
27 bool vis[MAXN];
28 int st[MAXN],top;
29 void add(int u,int v) {next[++cnt]=first[u],first[u]=cnt,to[cnt]=v;}
30 void tarjan(int x)
31 {
32 low[x]=dfn[x]=++stp,st[++top]=x,vis[x]=1;
33 for(int i=first[x];i;i=next[i])
34 {
35 if(!dfn[to[i]])
36 {
37 tarjan(to[i]);low[x]=min(low[x],low[to[i]]);
38 }
39 else if(vis[to[i]]) low[x]=min(low[x],dfn[to[i]]);
40 }
41 if(low[x]==dfn[x])
42 {
43 scc++,minn[scc]=inf;
44 while(st[top+1]!=x) minn[scc]=min(st[top],minn[scc]),bl[st[top]]=scc,num[scc]++,vis[st[top]]=0,top--;
45 }
46 }
47 int main()
48 {
49 n=read(),m=read();
50 int t,a,b;
51 while(m--)
52 {
53 a=read(),b=read(),t=read();
54 if(t==1) add(a,b);
55 else {add(a,b);add(b,a);}
56 }
57 for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i);
58 int tmp=0,k;
59 for(int i=1;i<=scc;i++) if(num[i]>=tmp||(num[i]==tmp&&minn[i]<minn[tmp])) tmp=num[i],k=i;
60 printf("%d
",tmp);
61 for(int i=1;i<=n;i++) if(bl[i]==k) printf("%d ",i);
62 }