(转载) poj1236 - Network of Schools
看到一篇挺好的代码,适合初学者,转载自 博主 wangjian8006
原地址:http://blog.csdn.net/wangjian8006/article/details/7888558
题目大意:有N个学校,从每个学校都能从一个单向网络到另外一个学校,两个问题
1:初始至少需要向多少个学校发放软件,使得网络内所有的学校最终都能得到软件。
2:至少需要添加几条边,使任意向一个学校发放软件后,经过若干次传送,网络内所有的学校最终都能得到软件。
解题思路:
首先找连通分量,然后看连通分量的入度为0点的总数,出度为0点的总数,那么问要向多少学校发放软件,就是入度为零的个数,这样才能保证所有点能够找到
然后第二问添加多少条边可以得到使整个图达到一个强连通分量,答案是入度为0的个数和出度为0的个数中最大的那个
为什么会这样呢,经过我同学的讨论,将这个图的所有子树找出来,然后将一棵子树的叶子结点(出度为0)连到另外一棵子树的根结点上(入度为0),这样将所有的叶子结点和根节点全部消掉之后,就可以得到一整个强连通分量,看最少多少条边,这样就是看叶子结点和根节点哪个多,即出度为0和入度为0哪个多。我只能说这种策略是正确的,适用于一般图,但其实我觉得也不能够很有力的证明这个结论成立
/*
kosaraju
Memory 224K
Time 0MS
*/
#include <iostream>
using namespace std;
#define MAXV 110
#define max(a,b) (a>b?a:b) int map[MAXV][MAXV],order[MAXV],belong[MAXV],indegree[MAXV],outdegree[MAXV];
int n,num,count;
bool vis[MAXV]; void dfs(int x){
int i;
vis[x]=;
for(i=;i<=n;i++)
if(map[x][i] && !vis[i])
dfs(i);
order[++num]=x;
} void dfst(int x){
int i;
belong[x]=count; //记录结点属于哪个连通分量
vis[x]=;
for(i=;i<=n;i++)
if(!vis[i] && map[i][x])
dfst(i);
} void kosaraju(){
int i;
memset(vis,,sizeof(vis));
num=count=;
for(i=;i<=n;i++) //第一次搜索将时间戳从小到大排序
if(!vis[i]) dfs(i);
memset(vis,,sizeof(vis)); for(i=n;i>=;i--) //第二次搜索从时间戳大的开始走找连通分量
if(!vis[order[i]]){
count++; //连通分量个数
dfst(order[i]);
}
} void output(){
int i,j,inzero=,outzero=;
for(i=;i<=n;i++){
indegree[i]=outdegree[i]=;
}
for(i=;i<=n;i++) //找连通分量入度与出度
for(j=;j<=n;j++)
if(map[i][j] && belong[i]!=belong[j]){
indegree[belong[j]]++;
outdegree[belong[i]]++;
}
for(i=;i<=count;i++){ //找入度与出度为0的点
if(!indegree[i]) inzero++;
if(!outdegree[i]) outzero++;
} if(count==) //只有1个结点要特判
printf("1\n0\n");
else
printf("%d\n%d\n",inzero,max(inzero,outzero));
} int main(){
int i,a;
while(~scanf("%d",&n)){
for(i=;i<=n;i++){
while(scanf("%d",&a) && a) map[i][a]=;
}
kosaraju();
output();
}
return ;
}
另一个用tarjan算法的实现
/*
tarjan
Memory 224K
Time 0MS
*/
#include <iostream>
using namespace std;
#define MAXV 110
#define min(a,b) (a>b?b:a)
#define max(a,b) (a>b?a:b) int n,map[MAXV][MAXV],outdegree[MAXV],indegree[MAXV];
int dfn[MAXV]; //第一次访问的步数
int low[MAXV]; //子树中最早的步数
int stap[MAXV],stop; //模拟栈
bool instack[MAXV]; //是否在栈中
int count; //记录连通分量的个数
int cnt; //记录搜索步数
int belong[MAXV]; //属于哪个连通分量 void init(){
count=stop=cnt=;
memset(instack,false,sizeof(instack));
memset(map,,sizeof(map));
memset(dfn,,sizeof(dfn));
} void tarjan(int x){
int i;
dfn[x]=low[x]=++cnt;
stap[stop++]=x;
instack[x]=true;
for(i=;i<=n;i++){
if(!map[x][i]) continue;
if(!dfn[i]){
tarjan(i);
low[x]=min(low[i],low[x]);
}else if(instack[i])
low[x]=min(dfn[i],low[x]);
//与x相连,但是i已经被访问过,且还在栈中
//用子树节点更新节点第一次出现的时间
} if(low[x]==dfn[x]){
count++;
while(){
int tmp=stap[--stop];
belong[tmp]=count;
instack[tmp]=false;
if(tmp==x) break;
}
}
} void output(){
int i,j,inzero=,outzero=;
for(i=;i<=n;i++){
indegree[i]=outdegree[i]=;
}
for(i=;i<=n;i++) //找连通分量入度与出度
for(j=;j<=n;j++)
if(map[i][j] && belong[i]!=belong[j]){
indegree[belong[j]]++;
outdegree[belong[i]]++;
}
for(i=;i<=count;i++){ //找入度与出度为0的点
if(!indegree[i]) inzero++;
if(!outdegree[i]) outzero++;
} if(count==) //只有1个结点要特判
printf("1\n0\n");
else
printf("%d\n%d\n",inzero,max(inzero,outzero));
} int main(){
int i,a;
while(~scanf("%d",&n)){
init();
for(i=;i<=n;i++){
while(scanf("%d",&a) && a) map[i][a]=;
}
for(i=;i<=n;i++)
if(!dfn[i]) tarjan(i);
output();
}
return ;
}
(转载) poj1236 - Network of Schools的更多相关文章
- P2746 [USACO5.3]校园网Network of Schools// POJ1236: Network of Schools
P2746 [USACO5.3]校园网Network of Schools// POJ1236: Network of Schools 题目描述 一些学校连入一个电脑网络.那些学校已订立了协议:每个学 ...
- poj-1236.network of schools(强连通分量 + 图的入度出度)
Network of Schools Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 27121 Accepted: 10 ...
- POJ1236 - Network of Schools tarjan
Network of Schools Time Limit: 1000MS Memory Limi ...
- POJ1236 Network of Schools (强连通)(缩点)
Network of Schools Time Limit: 1000MS ...
- POJ-1236 Network of Schools,人生第一道Tarjan....
Network of Schools 题意:若干个学校组成一个计算机网络系统,一个学校作为出发端连接着若干个学校,信息可以传送到这些学校.被链接的学校不需要再次与出发端相连,现在问你:A:最少选几个学 ...
- POJ1236 Network of Schools —— 强连通分量 + 缩点 + 入出度
题目链接:http://poj.org/problem?id=1236 Network of Schools Time Limit: 1000MS Memory Limit: 10000K Tot ...
- POJ1236 Network of Schools (强连通分量,注意边界)
A number of schools are connected to a computer network. Agreements have been developed among those ...
- poj1236 Network of Schools【强连通分量(tarjan)缩点】
转载请注明出处,谢谢:http://www.cnblogs.com/KirisameMarisa/p/4316263.html ---by 墨染之樱花 [题目链接]http://poj.org/pr ...
- POJ1236 network of schools
100个学校,有单向网络连接,从而分享软件. 问题一:几个学校得到软件就可使所有学校都得到? 问题二:再加几条单向网络可以使得"任意学校得到软件,就可使得所有学校都有软件"? -- ...
随机推荐
- Joomla - 菜单系统 (从创建到前端页面显示的过程)
在 Joomla 中,菜单是最常用且重要的功能之一,一般用于承载页面内容和各内容间的切换.导航等,演绎着非常重要的角色: 一.新建菜单 进入后台,点击顶栏菜单 -> 菜单管理 -> 点击新 ...
- (转)第02节:在Canvas上画简单的图形
我们现在已经可以在HTML中使用Fabric.js库了,那这节我们就详细的学习一下如何在canvas上画出简单的图形. 在画东西之前我们需要了解画任何东西的基本三个步骤: 声明画布(canvas),用 ...
- 表单单选按钮input[type="radio"]
<!DOCTYPE html> <html lang="zh"> <head> <title></title> < ...
- 设定计算属性setter
<!DOCTYPE html> <html lang="zh"> <head> <title></title> < ...
- mariadb ROW格式复制下从库结构变更引发1677错误
stop slave;set global slave_type_conversions=ALL_LOSSY;start slave; 详细度娘slave_type_conversions的参数说明
- ES6之主要知识点(四)数值
引自:http://es6.ruanyifeng.com/#docs/number 1.Number.isFinite(),Number.isNaN() Number.isFinite(); // t ...
- JS实用插件
1. jQuery鼠标滚轮事件插件Mouse Wheel 下载链接:https://github.com/brandonaaron/jquery-mousewheel/ 使用方法: // using ...
- Errors were encountered while processing: mysql-server-5.5
ubuntu 中运行完sudo apt-get install curl之后,最后出现: ldconfig deferred processing now taking place Errors we ...
- Elasticsearch系列(二)--query、filter、aggregations
本文基于ES6.4版本,我也是出于学习阶段,对学习内容做个记录,如果文中有错误,请指出. 实验数据: index:book type:novel mappings: { "mappings& ...
- 自动化运维工具Ansible工具
目录 一.初识Ansible 二.Ansible的架构 三.Ansible基础使用 安装 主机清单 管理主机 四.Ansible用脚本管理主机 五.Ansible模块Module 六.Ansible常 ...