首页 > 代码库 > 【强连通分量】bzoj 1051 受欢迎的牛
【强连通分量】bzoj 1051 受欢迎的牛
1051: [HAOI2006]受欢迎的牛
时间限制: 10 Sec 内存限制: 162 MB提交: 2150 解决: 1129
[提交][]
题目描述
每一头牛的愿望就是变成一头最受欢迎的牛。现在有N头牛,给你M对整数(A,B),表示牛A认为牛B受欢迎。 这种关系是具有传递性的,如果A认为B受欢迎,B认为C受欢迎,那么牛A也认为牛C受欢迎。你的任务是求出有多少头牛被所有的牛认为是受欢迎的。
输入
第一行两个数N,M。 接下来M行,每行两个数A,B,意思是A认为B是受欢迎的(给出的信息有可能重复,即有可能出现多个A,B)
输出
一个数,即有多少头牛被所有的牛认为是受欢迎的。
样例输入
3 3
1 2
2 1
2 3
1 2
2 1
2 3
样例输出
1
提示
100%的数据N<=10000,M<=50000
来源
还是强连通分量的题
还是出度为0的缩点是所有牛都欢迎的
开始看成受欢迎的牛群有多少
然后就傻×的想有多个牛群怎么都会有所有的牛认为是受欢迎的
然后就看题解 =.= 我是渣
哎-----
# include<cstdio># include<cstring># include<stack># include<algorithm># include<iostream>using namespace std;const int N=10000+10;const int M=50000+10;stack<int>S;int n,m,ecnt,scc_cnt,dfs_clock,tot,out_degree,cur;int fist[N],next[M],v[M],pre[N],low[N],scc_no[N],size[N],out[N];void built(int a,int b){ ++ecnt; v[ecnt]=b; next[ecnt]=fist[a]; fist[a]=ecnt;}int check(int a,int b){ for(int e=fist[a];e!=-1;e=next[e]) if(v[e]==b)return 0; return 1;}void init(){ int a,b; memset(fist,-1,sizeof(fist)); scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ scanf("%d%d",&a,&b); // if(check(a,b)) built(a,b); }}int dfs(int u){ int lowu=pre[u]=++dfs_clock; S.push(u); for(int e=fist[u];e!=-1;e=next[e]) if(!pre[v[e]]) lowu=min(lowu,dfs(v[e])); else if(!scc_no[v[e]]) lowu=min(lowu,pre[v[e]]); low[u]=lowu; if(low[u]==pre[u]){ scc_cnt++; for(;;){ int x=S.top();S.pop(); scc_no[x]=scc_cnt; if(x==u)break; } } return low[u];}void find_scc(){ memset(pre,0,sizeof(pre)); memset(low,0,sizeof(low)); for(int i=1;i<=n;i++) if(!pre[i])dfs(i);}void work(){ for(int i=1;i<=n;i++)for(int e=fist[i];e!=-1;e=next[e]) if(scc_no[i]!=scc_no[v[e]])out[scc_no[i]]++; for(int i=1;i<=scc_cnt;i++)if(out[i]==0)out_degree=i; for(int i=1;i<=n;i++)if(scc_no[i]==out_degree)tot++; printf("%d",tot);}int main(){ init(); find_scc(); work(); return 0;}
【强连通分量】bzoj 1051 受欢迎的牛
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。