[HAOI2006]受欢迎的牛 scc分解(下标从1)

来源:互联网 发布:linux中如何删除用户 编辑:程序博客网 时间:2024/05/21 09:06

如果有x满足答案,x所在的scc也满足答案

合法scc个数不会超过1,因为这样的话2个scc是传递的,应该可以合并才对

这个板子做法是按照拓扑序排列缩点后的图的,所以可能成为答案的scc一定是最后那个

//#include<iostream>#include<stdio.h>#include<algorithm>#include<queue>#include<string.h>#include<math.h>#include<set>#include<map>#include<vector>#include<iomanip>#include<stack>using namespace std;#define ll long long#define ull unsigned long long#define pb push_back#define mem(a) memset(a,0,sizeof a)#define FOR(a) for(int i=1;i<=a;i++)const int maxn=1e4+6;int V;vector<int>G[maxn];vector<int>rG[maxn];vector<int>vs;//后续bool used[maxn];int cmp[maxn];//所属连通分量拓扑序void addedge(int u,int v){G[u].pb(v);rG[v].pb(u);}void dfs(int u){used[u]=1;for(int i=0;i<G[u].size();i++){if(!used[G[u][i]])dfs(G[u][i]);}vs.pb(u);}void rdfs(int u,int k){used[u]=1;cmp[u]=k;for(int i=0;i<rG[u].size();i++){if(!used[rG[u][i]])rdfs(rG[u][i],k);}}int scc(){memset(used,0,sizeof used);vs.clear();for(int i=1;i<=V;i++){if(!used[i])dfs(i);}memset(used,0,sizeof used);int k=0;for(int i=vs.size()-1;i>=0;i--){if(!used[vs[i]])rdfs(vs[i],++k);}return k;}int n,m;int main(){scanf("%d%d",&n,&m);V=n;for(int i=1,u,v;i<=m;i++){scanf("%d%d",&u,&v);addedge(u,v);}n=scc();int u=1,num=0;for(int i=1;i<=V;i++){if(cmp[i]==n){u=i;num++;}}memset(used,0,sizeof used);rdfs(u,0);for(int i=1;i<=V;i++){if(!used[i]){num=0;break;}}printf("%d\n",num);}