POJ2186 USACO 2003 Fall Popular Cows(强联通分支)
2015-07-21 21:18
531 查看
题目大意:有n只牛,给出一个受欢迎的关系,受欢迎的关系是单向的但是可以传递,当然,每只牛都是欢迎自己的。问有多少只牛收到所有牛的欢迎。
思路:首先我们要明确这是一张有向图。然后求出所有的强联通分量,把它们压缩成一个点,之后我们就会得到一棵树。最后统计树上入度为0的点,如果有不止一个入度为0的点,那么肯定是不符合题意的,因为这些入度为0的点不会互相欢迎。注意在这里树上入度为0的点可能并不是真正的一个点,有可能是经过我们压缩的强联通分支。
思路:首先我们要明确这是一张有向图。然后求出所有的强联通分量,把它们压缩成一个点,之后我们就会得到一棵树。最后统计树上入度为0的点,如果有不止一个入度为0的点,那么肯定是不符合题意的,因为这些入度为0的点不会互相欢迎。注意在这里树上入度为0的点可能并不是真正的一个点,有可能是经过我们压缩的强联通分支。
#include<cstdio> #include<cstring> #define MAXN 10005 #define Min(a,b) a<b?a:b using namespace std; struct e { int v; int next; }edge[100005]; int cnt; int head[MAXN]; void add_edge(int u,int v) { edge[cnt].v = v; edge[cnt].next = head[u]; head[u] = cnt++; } int n,m; int dcnt,low[MAXN],dfn[MAXN]; bool instack[MAXN]; int stack[MAXN],tot; int cut_e; int belong[MAXN]; int in[MAXN]; void dfs(int u) { low[u] = dfn[u] = ++dcnt;//按访问先后顺序标号 stack[++tot] = u;//u进栈 instack[u] = true;//判断横叉边 for(int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].v; if(dfn[v] == -1) { dfs(v);//u,v为父子边 low[u] = Min(low[u],low[v]); } else if(instack[v])//u,v是返祖边 { low[u] = Min(low[u],dfn[v]); } } if(low[u] == dfn[u])//u是连通分量的根 { cut_e++;//连通分量数加1 do { belong[stack[tot]] = cut_e;//记录属于第几个连通分量 instack[stack[tot]] = false;//出栈 tot--; }while(stack[tot+1] != u); } } int main() { while(scanf("%d%d",&n,&m) != EOF) { memset(head,-1,sizeof head); memset(edge,0,sizeof edge); memset(low,0,sizeof low); memset(dfn,-1,sizeof dfn); memset(instack,0,sizeof instack); memset(stack,0,sizeof stack); memset(belong,0,sizeof belong); memset(in,0,sizeof in); tot = 0; cnt = dcnt = 0; cut_e = 0; for(int i = 1; i <= m; i++) { int a,b; scanf("%d%d",&a,&b); add_edge(a,b);//有向图,立碑纪念 } for(int i = 1; i <= n; i++) if(dfn[i] == -1) dfs(i); for(int i = 1; i <= n; i++)//同一个连通分量里的所有点看做一个点 { for(int j = head[i]; j != -1; j = edge[j].next) { int v = edge[j].v; if(belong[i] != belong[v])//统计入度 { in[belong[i]]++; } } } int cnt = 0,cntx; for(int i = 1; i <= cut_e; i++)//统计入度,只能有一个入度为0的点 if(!in[i]) { cnt++; cntx = i; } if(cnt == 1) { int sum = 0; for(int i = 1; i <= n; i++) if(belong[i] == cntx) sum++; printf("%d\n",sum); } else printf("0\n"); } }
相关文章推荐
- Nginx之红黑树
- fork系统调用的执行过程
- 从零开始搭建hadoop分布式集群环境:(一)新建hadoop用户以及用户组
- 配置IIS6出现 出现验证码无法显示问题
- 19_Android中图片处理原理篇,关于人脸识别网站,图片加载到内存,图片缩放,图片翻转倒置,网上撕衣服游戏案例编写
- linux下python安装 nose lapack atlas numpy scipy sklearn
- u盘启动lfslivecd-x86-6.3-r2145.iso
- Linux cut 命令
- 通过串口连接linux配置过程
- 通过串口连接linux配置过程
- 工作积累(七)——Tomcat URIEncoding引起的中文乱码问题
- 多学一点(十三)——解决Linux kdump服务启动失败
- 多学一点(十一)——配置使用Tomcat Manager进行可视化部署
- 多学一点(十)——配置一个Tomcat使其可以多端口访问
- 学习笔记(十一)——Linux Shell 基础知识
- 多学一点(五)——在Linux下安装配置Apache
- 多学一点(六)——在Linux下安装配置MySQL
- 多学一点(七)——不重启Linux添加磁盘,使用软链接为挂载点扩容
- 多学一点(四)——在 Linux 下配置多个 Tomcat
- 多学一点(二)——在 Linux 下挂载 Windows 共享目录、使用 scp 命令在两台 Linux 间传输数据