首页 > 学院 > 开发设计 > 正文

文章标题

2019-11-08 18:42:09
字体:
来源:转载
供稿:网友

原题 比较经典吧 (洛谷上粘的) [HAOI2006]受欢迎的牛 题目描述 每头奶牛都梦想成为牛棚里的明星。被所有奶牛喜欢的奶牛就是一头明星奶牛。所有奶

牛都是自恋狂,每头奶牛总是喜欢自己的。奶牛之间的“喜欢”是可以传递的——如果A喜

欢B,B喜欢C,那么A也喜欢C。牛栏里共有N 头奶牛,给定一些奶牛之间的爱慕关系,请你

算出有多少头奶牛可以当明星。

输入输出格式

输入格式:  第一行:两个用空格分开的整数:N和M

 第二行到第M + 1行:每行两个用空格分开的整数:A和B,表示A喜欢B

输出格式:  第一行:单独一个整数,表示明星奶牛的数量

输入输出样例

输入样例#1: 3 3 1 2 2 1 2 3 输出样例#1: 1 说明

只有 3 号奶牛可以做明星

【数据范围】

10%的数据N<=20, M<=50

30%的数据N<=1000,M<=20000

70%的数据N<=5000,M<=50000

100%的数据N<=10000,M<=50000

其实是一个强连通分量的基础题,我是用的 tarjan 首先要 理解Tarjan的原理 并能掌握其代码模板(我这没讲,去百度查); 然后在 Tarjan 深搜完后退栈时做个小记录就行了,我感觉所谓缩点其实没真缩(因为没有建新图嘛), 只是统计了一下每个点所属的强连通分量,以及每个分量 所含点的数量,tarjan完了之后遍历每个边, 记了每个分量的出度(只有唯一一个出度为零的分量才能成明星),看是否只有一个满足的分量,然 后得到答案(即那个分量所含的点数); 看代码

#include<iostream>#include<cstdio>#include<cstring>using namespace std;int n,m;int top,stack[100010];bool instack[100010];// zhanint dfn[100010],low[100010],step;//tarjanint belong[100010],outd[100010],mem[100010],totq,popular,ans;//suo dianint cnt,last[100010];struct E{ int to,fro,next;}a[500010]; //lian shi qiang xiang xingvoid bud(int u,int v){ a[++cnt].to=v;a[cnt].fro=u;a[cnt].next=last[u];last[u]=cnt;} void tarjan(int x){ dfn[x]=low[x]=++step; stack[++top]=x;instack[x]=1; for(int i=last[x];i;i=a[i].next){ if(!dfn[a[i].to]){ tarjan(a[i].to); if(low[x]>low[a[i].to]) low[x]=low[a[i].to]; } else if(instack[a[i].to]&&low[x]>dfn[a[i].to]) low[x]=dfn[a[i].to]; } if(dfn[x]==low[x]){ totq++;int t; do{ t=stack[top]; instack[t]=0; belong[t]=totq; mem[totq]++; top--; }while(t!=x); }}int main(){ freopen("in.txt","r",stdin); scanf("%d%d",&n,&m); for(int i=1;i<=m;++i) { int u,v; scanf("%d%d",&u,&v); bud(u,v); } for(int i=1;i<=n;++i){ if(!dfn[i]) tarjan(i); } for(int i=1;i<=m;++i) if(belong[a[i].fro]!=belong[a[i].to]) outd[belong[a[i].fro]]++; for(int i=1;i<=totq;++i){ if(outd[i]==0){ popular++; ans=i; } } if(popular==1)PRintf("%d",mem[ans]); else printf("0"); return 0;}
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表