1. 程式人生 > >[CodeVS2822]愛在心中

[CodeVS2822]愛在心中

getchar pop cst -- sign char -1 for col

思路:
Tarjan+縮點。
首先跑一遍Tarjan,統計結點個數大於$1$的連通分量個數。然後尋找統計結點個數大於$1$且出度為$0$的連通分量,若只存在一個這樣的連通分量,輸出其點集即可。

 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=100001; 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],low[V],scc[V],id=0,cnt=0; 18 bool ins[V]; 19 std::stack<int
> s; 20 void Tarjan(const int x) { 21 low[x]=dfn[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=x; 37 do { 38 y=s.top(); 39 s.pop(); 40 ins[y]=false; 41 scc[y]=id; 42 } while(y!=x); 43 } 44 } 45 int out[V]={0},size[V]={0}; 46 int main() { 47 int n=getint(); 48 for(int m=getint();m;m--) { 49 int u=getint(),v=getint(); 50 add_edge(u,v); 51 } 52 for(int i=1;i<=n;i++) { 53 if(!dfn[i]) Tarjan(i); 54 } 55 for(int x=1;x<=n;x++) { 56 size[scc[x]]++; 57 for(unsigned i=0;i<e[x].size();i++) { 58 int &y=e[x][i]; 59 if(scc[x]!=scc[y]) out[scc[x]]++; 60 } 61 } 62 int ans1=0,cnt=0; 63 std::vector<int> ans; 64 for(int i=1;i<=id;i++) { 65 if(size[i]>1) ans1++; 66 if(out[i]) continue; 67 if(size[i]==1) continue; 68 cnt++; 69 for(int j=1;j<=n;j++) { 70 if(scc[j]==i) ans.push_back(j); 71 } 72 } 73 printf("%d\n",ans1); 74 if(cnt==1) { 75 for(unsigned i=0;i<ans.size();i++) { 76 printf("%d ",ans[i]); 77 } 78 } 79 else puts("-1"); 80 return 0; 81 }

[CodeVS2822]愛在心中