luogu 1726 上白泽惠音

题目大意:

给一个有向图

求一个最大的强连通分量,输出这个强连通分量里的所有元素

若两个联通分量内点数相同 则输出字典序小的那个

思路:

直接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\n",tmp);
61     for(int i=1;i<=n;i++) if(bl[i]==k) printf("%d ",i);
62 }
View Code
posted @ 2017-10-30 16:49  jack_yyc  阅读(171)  评论(0编辑  收藏  举报