SP6818 CAPCITY - Capital City 题解
因为图中有环,考虑缩点。
缩点之后考虑什么样的点可以成为首都。显然最多一个 SCC 内会产生首都——假设我们对缩完点的所有 SCC 进行一次拓扑排序,一定是仅有一个出度为
这样只用统计出度并判断出度为
放代码:
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
int main(){
ios::sync_with_stdio(false);
int n,m,o=0,r=-1; cin>>n>>m;
vector<pii> e(m);
vector<vector<int> > g(n);
for(auto &[u,v]:e)
cin>>u>>v,g[--u].emplace_back(--v);
// SPOJ 的评测机是 C++14 的,写代码时可相应替换
vector<int> d(n),l(n),c(n,-1);
stack<int> s;
function<void(int)> tarjan=[&](int u){
d[u]=l[u]=++o,s.emplace(u);
for(int i:g[u])
if(!d[i])tarjan(i),l[u]=min(l[u],l[i]);
else if(c[i]<0)l[u]=min(l[u],d[i]);
if(d[u]==l[u]){
r++; while(s.top()!=u)
c[s.top()]=r,s.pop();
c[u]=r,s.pop();
}
};
for(int i=0;i<n;i++)
if(!d[i])tarjan(i); // tarjan 模板
map<pii,bool> p;
d.resize(r+1),fill(d.begin(),d.end(),0);
for(auto [u,v]:e)
if(c[u]!=c[v]&&!p[make_pair(c[u],c[v])])
p[make_pair(c[u],c[v])]=true,d[c[u]]++;
bool f=true;
for(int i=0;i<=r;i++)
if(!d[i]){
if(f)f=false; // 第一次
else cout<<"0\n",exit(0); // 第二次,不唯一,无解
}
for(int i=0;i<=r;i++)
if(!d[i]){
vector<int> w;
for(int j=0;j<n;j++)
if(c[j]==i)w.emplace_back(j);
cout<<w.size()<<endl;
for(int i:w)cout<<i+1<<' ';
cout<<endl; break;
} // 找出那个特定的 SCC
return 0;
}