wannafly挑战赛14 C可达性
src:https://www.nowcoder.com/acm/contest/81/C
输出一个尽可能小的点集,使得从这些点出发能够到达任意一点,如果有多个这样的集合,输出这些集合升序排序后字典序最小的。
缩点后入度为0的都是了~~~
ac代码:
#include <iostream> #include<cstdlib> #include<algorithm> #include<cmath> #include<functional> #include<utility> #include<string> #include<string.h> #include<vector> #include<iomanip> #include<stack> using namespace std; #define FOR(i,a,b) for(int i=a;i<=b;i++) vector<int>edge[100005],ans; int n,m,vis[100005],a,b,idx=0,scc[100005],nscc=0,in[100005],tmp,dfn[100005],low[100005];//in表示强分量入度 stack<int>st; vector<int>id[100005]; bool InStack[100005]; void tarjan(int u) { dfn[u]=low[u]=++idx; st.push(u);InStack[u]=true; for(vector<int>::iterator it=edge[u].begin();it!=edge[u].end();++it) { if(!dfn[*it]){ tarjan(*it);low[u]=min(low[u],low[*it]); } else if(InStack[*it]) low[u]=min(low[u],dfn[*it]); } if(dfn[u]==low[u]){ nscc++; do{ tmp=st.top();st.pop(); InStack[tmp]=false; scc[tmp]=nscc; id[nscc].push_back(tmp); }while(tmp!=u); } } void condense() { for(int i=1;i<=n;++i){ if(dfn[i]==0){ tarjan(i); } } } int main() { std::ios::sync_with_stdio(false); cin>>n>>m; int tmp; for(int i=1;i<=m;i++){ cin>>a>>b; if(a==b)continue; edge[a].push_back(b); } condense(); memset(vis,false,sizeof(vis)); for(int i=1;i<=n;i++){ for(vector<int>::iterator it=edge[i].begin();it!=edge[i].end();++it){ tmp=*it; if(scc[i]!=scc[tmp]){in[scc[tmp]]++;} } } FOR(i,1,nscc)sort(id[i].begin(),id[i].end()); vector<int>ans; for(int i=1;i<=nscc;i++)if(!in[i])ans.push_back(id[i][0]); cout<<ans.size()<<endl; sort(ans.begin(),ans.end()); cout<<ans[0]; for(int i=1;i<ans.size();i++)cout<<' '<<ans[i]; cout<<endl; return 0; }

浙公网安备 33010602011771号