POJ1236Network of Schools——强连通分量缩点建图

【题目描述】

A number of schools are connected to a computer network. Agreements have been developed among those schools: each school maintains a list of schools to which it distributes software (the “receiving schools”). Note that if B is in the distribution list of school A, then A does not necessarily appear in the list of school B
You are to write a program that computes the minimal number of schools that must receive a copy of the new software in order for the software to reach all schools in the network according to the agreement (Subtask A). As a further task, we want to ensure that by sending the copy of new software to an arbitrary school, this software will reach all schools in the network. To achieve this goal we may have to extend the lists of receivers by new members. Compute the minimal number of extensions that have to be made so that whatever school we send the new software to, it will reach all other schools (Subtask B). One extension means introducing one new member into the list of receivers of one school.

Input

The first line contains an integer N: the number of schools in the network (2 <= N <= 100). The schools are identified by the first N positive integers. Each of the next N lines describes a list of receivers. The line i+1 contains the identifiers of the receivers of school i. Each list ends with a 0. An empty list contains a 0 alone in the line. 

Output

Your program should write two lines to the standard output. The first line should contain one positive integer: the solution of subtask A. The second line should contain the solution of subtask B. 

Sample Input

5
2 4 3 0
4 5 0
0
0
1 0

Sample Output

1
2

【题目分析】
有一些学校,现在他们之间可以存在发送软件的关系
A. 问最少给几个学校发送软件就可以让所有学校受到软件
B. 问最少加多少条边后给任意学校发送软件所有的学校都可以收到软件
我们进行强连通分量缩点建图之后统计所有入度为0和出度为0的点,入度为0 的点的数目就是A问题的答案。
对于B问题,答案是入度为0的点和出度为0的点的较大值。
原因我在网上没有找到答案,大家都说答案就是较大值,可是我却一直不太能理解。后来觉得可能存在数学证明什么的可以证明这样一定存在一种方式可以将一个DAG变成一个强连通分量。
我自己的理解的话,首先我们将所有出度为0的点连在不能到达该点的入度为0的点上,最后肯定会形成一个环,通过这个环所有的点都可以相互到达,而剩下的入度为0 的点或者出度为0 的点可以随意连在其他点上,这样就将一个DAG变化为一个强连通图
需要注意的是如果原本的图就是一个强连通图就不要加边,需要特判。

【AC代码】

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<climits>
#include<queue>
#include<vector>
#include<set>
#include<map>
using namespace std;typedef long long ll;
const int MAXN=1e2+5;
const int MAXM=1e4+5;struct node
{int v,next;
}Edge[MAXM];
int head[MAXN],tot;
int DFN[MAXN],LOW[MAXN];
int color[MAXN],cnt;
bool vis[MAXN];
int idx;
int stack[MAXN],top;
int In[MAXN],Out[MAXN];
int n;
int ans1,ans2,ans3;
int Case=0;void init()
{memset(head,0,sizeof(head)); tot=0;idx=0; memset(vis,0,sizeof(vis));memset(DFN,0,sizeof(DFN));memset(color,0,sizeof(color));cnt=0; top=0;memset(In,0,sizeof(In));memset(Out,0,sizeof(Out));
}void AddEdge(int u,int v)
{tot++;Edge[tot].v=v; Edge[tot].next=head[u];head[u]=tot;
}void read()
{int u,v;for(int i=1;i<=n;i++){while(~scanf("%d",&v) && v){AddEdge(i,v);}}
}void Trajan(int x)
{int v,tmp;DFN[x]=LOW[x]=++idx;stack[++top]=x; vis[x]=true;for(int i=head[x];i;i=Edge[i].next){v=Edge[i].v;if(!DFN[v]){Trajan(v);if(LOW[v]<LOW[x]) LOW[x]=LOW[v];}else if(vis[v] && DFN[v]<LOW[x]){LOW[x]=DFN[v];  }}if(DFN[x]==LOW[x]){cnt++;do{tmp=stack[top--];vis[tmp]=false;color[tmp]=cnt;}while (tmp!=x);}
}void solve()
{int v;for(int i=1;i<=n;i++){if(!DFN[i])Trajan(i);}for(int i=1;i<=n;i++){for(int j=head[i];j;j=Edge[j].next){v=Edge[j].v;if(color[i]!=color[v]){In[color[v]]++;Out[color[i]]++;}}}ans1=0; ans2=0;int minc;for(int i=1;i<=cnt;i++){if(!In[i]){ans1++;}if(!Out[i]){ans2++;}}if(cnt==1) ans3=0;else ans3=max(ans1,ans2);printf("%d\n%d\n",ans1,ans3);
}int main()
{while(~scanf("%d",&n) && n){init();read();solve();}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/384056.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C——通过调用函数分配内存

http://blog.csdn.net/u012627502/article/details/3579724 1&#xff09;以返回值方式返回&#xff1a;把动态分配的存储位置地址&#xff0c;赋值给指针类型返回值&#xff08;不同于被调用函数的自动变量地址&#xff09; 2&#xff09;以形参形式返回&#xff1a;二级指针类…

gdb调试多进程程序

1.gdb下调试多进程程序只需要以下几条命令即可              除此之外还可以查看正在调试的进程 info inferiors, 同时也可以将当前正在调试的进程切换到另外一个进程中让其取运行     2.代码调试演示 #include<stdio.h> #include<stdlib.h> #…

BZOJ1123-BLO——强连通分量求割点+计数

【题目描述】 Byteotia城市有n个 towns m条双向roads. 每条 road 连接 两个不同的 towns ,没有重复的road. 所有towns连通。Input 输入n<100000 m<500000及m条边Output 输出n个数&#xff0c;代表如果把第i个点去掉&#xff0c;将有多少对点不能互通。Sample Input 5…

关于memcpy和memmove两函数的区别

http://blog.csdn.net/caowei840701/article/details/8491836 [cpp] view plaincopy <p> 关于memcpy和memmove两个c标准库函数&#xff0c;其功能都是将一块内存区域中的指定大小内容复制到目标内存中&#xff0c;在翻阅c标准库实现的源代码我们发现他们是有区别的。&…

判断字符串出栈合法性

先来看说一下思路 接下来就是写代码了 int StackOrder(SeqStack* stack, char* input, char* output, int size_input, int size_output) {if(stack NULL || input NULL || output NULL){return 0;}int i_input 0;int j_output 0;SeqStackType value;for(; j_output <…

CodeForces - 1200C——小模拟

【题目描述】 Amugae is in a very large round corridor. The corridor consists of two areas. The inner area is equally divided by n sectors, and the outer area is equally divided by m sectors. A wall exists between each pair of sectors of same area (inner o…

1 单例模式

达内 闵大神 //饿汉单例模式 #include <iostream> using namespace std;class Singleton { public:static Singleton& getInstance(){return s_instance;} private:Singleton(){}Singleton(const Singleton& that){}static Singleton s_instance;//静态成员变量 …

共享栈

1.定义 所谓共享栈就是利用一个数组实现两个栈. 先来看一下共享栈的数据结构 typedef struct SharedStack {int top1;int top2;SeqStackType* data; }SharedStack; 2. 初始化 void SharedStackInit(SharedStack* stack) {if(stack NULL){return;//非法输入}stack -> top…

BZOJ1018 | SHOI2008-堵塞的交通traffic——线段树维护区间连通性+细节

【题目描述】 BZOJ1018 | SHOI2008-堵塞的交通traffic 有一天&#xff0c;由于某种穿越现象作用&#xff0c;你来到了传说中的小人国。小人国的布局非常奇特&#xff0c;整个国家的交通系统可 以被看成是一个2行C列的矩形网格&#xff0c;网格上的每个点代表一个城市&#xff0…

C++ 函数隐藏

C该函数隐藏 只有基类成员函数的定义已声明virtualkeyword&#xff0c;当在派生类中的时间&#xff0c;以支付功能实现&#xff0c;virtualkeyword可以从时间被添加以增加。它不影响多状态。 easy混淆视听&#xff0c;掩盖&#xff1a; &#xff0c;规则例如以下&#xff1a; …

迷宫求解(递归)

首先来看一下迷宫简易图                                  我们用 0 来表示该位置是墙, 用 1 来表示该位置是路. 所以, 我们在处理迷宫问题的时候可以将其看成一个二维数组即可, 而对应的每一条路我们可以用坐标的形式将其表示, 所以还需要…

CodeForces - 786C——二分+模拟?

【题目描述】 Rick and Morty want to find MR. PBH and they cant do it alone. So they need of Mr. Meeseeks. They Have generated n Mr. Meeseeks, standing in a line numbered from 1 to n. Each of them has his own color. i-th Mr. Meeseeks color is ai.Rick and M…

迷宫求解(非递归)

上篇文章写出了利用函数形成栈桢的特性完成迷宫求解问题, 本篇文章我们自己手动维护一个栈, 其进行出栈, 入栈, 取栈顶元素, 来完成迷宫求解寻路的过程     思路和以前一样, 首先, 我们先定义一个栈, 对其初始化, 同时, 定义一个迷宫地图, 对该地图进行初始化, 先判断当前…

数据结构练习——双向链表

http://www.cnblogs.com/-Lei/archive/2012/04/10/2440399.html 复习一下数据结构。。。。说不准下个星期就用上了 只不过写的很简单&#xff0c;没有封装 DoubleLinkList.h #ifndef GUARD_DoubleLinkList_h #define GUARD_DoubleLinkList_h#include <stdio.h>struct Li…

CodeChef - DGCD——树链剖分+差分

【题目描述】 Youre given a tree on N vertices. Each vertex has a positive integer written on it, number on the ith vertex being vi. Your program must process two types of queries :1. Find query represented by F u v : Find out gcd of all numbers on the uniq…

UVa272-TeX中的引号

【题目描述】 传送门 【题目分析】 今天开始刷紫书的题目啦 这道题很简单&#xff0c;需要注意的是cgetchar()需要加上括号&#xff0c;因为赋值语句的优先级比判等低 而且书中说好像最好用整型变量&#xff0c;因为EOF的值为-1&#xff0c;在字符变量中没有这个值。&#xf…

C++中友元(友元函数和友元类)的用法和功能

http://blog.csdn.net/adriano119/article/details/5914443/ 采用类的机制后实现了数据的隐藏与封装&#xff0c;类的数据成员一般定义为私有成员&#xff0c;成员函数一般定义为公有的&#xff0c;依此提供类与外界间的通信接口。但是&#xff0c;有时需要定义一些函数&#x…

线程的终止分离

1.线程的终止 注意该函数是针对用户级别的, 其中 retal 必须指向一个全局变量, 或者是一个 malloc 分配的, 因为如果是线程的局部变量, 当该线程退出时, 其他线程不能得到这个变量, 因为线程的局部变量各自私有 2. 现成的取消 其中thread是线程的 tid 3.线程的等待与分离 (1)…

UVa10082

【题目描述】 传送门 【题目分析】 同样是一道模拟&#xff0c;但是如何巧妙快速的解决仍然不简单。通过这道题告诉我们对于复杂确定的对应关系我们要灵活运用常量数组。 同时还需要注意的一个小问题就是字符串数组中的"//"指的是转义后的单斜杠&#xff0c;如果只…

C语言中的深拷贝和浅拷贝

http://www.cnblogs.com/zhanggaofeng/p/5421804.html C语言中的深拷贝和浅拷贝 //C语言中的深拷贝和浅拷贝 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> #include<string.h>typedef struct _student{char name[30];char *title;…