[洛谷1726]上白泽慧音

思路:
Tarjan求出所有的连通分量,然后$O(n)$计算每个连通分量的大小,再$O(n)$找出字典序最小的。

 1 #include<stack>
 2 #include<cstdio>
 3 #include<cctype>
 4 #include<vector>
 5 inline int getint() {
 6     char ch;
 7     while(!isdigit(ch=getchar()));
 8     int x=ch^'0';
 9     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
10     return x;
11 }
12 const int V=5001;
13 std::vector<int> e[V];
14 inline void add_edge(const int u,const int v) {
15     e[u].push_back(v);
16 }
17 int dfn[V]={0},low[V]={0},scc[V]={0},cnt=0,id=0;
18 bool ins[V]={0};
19 std::stack<int> s;
20 void Tarjan(const int x) {
21     dfn[x]=low[x]=++cnt;
22     s.push(x);
23     ins[x]=true;
24     for(unsigned i=0;i<e[x].size();i++) {
25         int &y=e[x][i];
26         if(!dfn[y]) {
27             Tarjan(y);
28             low[x]=std::min(low[x],low[y]);
29         }
30         else if(ins[y]) {
31             low[x]=std::min(low[x],dfn[y]);
32         }
33     }
34     if(dfn[x]==low[x]) {
35         id++;
36         int y;
37         do {
38             y=s.top();
39             s.pop();
40             scc[y]=id;
41             ins[y]=false;
42         } while(x!=y);
43     }
44 }
45 int size[V];
46 int main() {
47     int n=getint();
48     for(int m=getint();m;m--) {
49         int u=getint(),v=getint(),t=getint();
50         if(t==1) {
51             add_edge(u,v);
52         }
53         else {
54             add_edge(u,v);
55             add_edge(v,u);
56         }
57     }
58     for(int i=1;i<=n;i++) {
59         if(!dfn[i]) Tarjan(i);
60     }
61     int maxsize=0;
62     for(int i=1;i<=n;i++) {
63         size[scc[i]]++;
64         maxsize=std::max(maxsize,size[scc[i]]);
65     }
66     printf("%d\n",maxsize);
67     int sccid;
68     for(int i=1;i<=n;i++) {
69         if(size[scc[i]]==maxsize) {
70             sccid=scc[i];
71             break;
72         }
73     }
74     for(int i=1;i<=n;i++) {
75         if(scc[i]==sccid) printf("%d ",i);
76     }
77     return 0;
78 }

 

posted @ 2017-08-20 15:23  skylee03  阅读(90)  评论(0编辑  收藏  举报