poj 1236 Network of Schools 强连通

来源:互联网 发布:淘宝上买的车衣不耐用 编辑:程序博客网 时间:2024/04/25 14:41

我的第一个强连通题目,利用这个题目入门。花了一晚上学习了啥是强连通和tarjan算法求强连通分量。感觉这个题只要理解了这个就可以做了,比较适合入门。

如果还不会的,可以先了解一下再看题。

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
52 4 3 04 5 0001 0
Sample Output
12
题意:给定一个有向图,问你1:从几个点开始可以遍历所有的点。问你2:多加几条边可以使这个图变成强连通图
做法:
1.求几个点开始,就是求有几个入度为0的强连通分量。
2,你让每个强连通分量入度和出度都不为0就行了,这样就都连通了。做法就是把入度为0的和出度为0的连接起来,配不上的单独连,这样的话就取max(入度为0的个数,出度为0的个数)。
#include<iostream>#include<algorithm>#include<cstring>#include<queue>#include<vector>#define ll long long#define ld long double#define INF 0x3f3f3f3fusing namespace std;vector<int> G[105];int vis[105],max_num=0,id[105];          //vis判断是否访问过,强连通分量个数,所属强连通分量 int stack[105],dfn[105],low[105];        //tarjan算法所用到的 int top=0,now_dfn=0,rd[105],cd[105];     void mem() {                              //初始化 memset(vis,0,sizeof vis);memset(id,0,sizeof id);memset(stack,0,sizeof stack);memset(dfn,0,sizeof dfn);memset(low,0,sizeof low);memset(rd,0,sizeof rd);memset(cd,0,sizeof cd);}void tarjan(int x) {                     //求强连通分量 vis[x]=1;stack[++top]=x;dfn[x]=low[x]=++now_dfn;for(int i=0; i<G[x].size(); i++) {int y=G[x][i];if(!vis[y]) {tarjan(y);low[x]=min(low[x],low[y]);} elselow[x]=min(low[x],dfn[y]);}if(low[x]==dfn[x]) {max_num++;int tmp;do {tmp=stack[top--];dfn[tmp]=INF;id[tmp]=max_num;} while(tmp!=x);}}int main() {//std::ios::sync_with_stdio(false);// freopen("in.txt", "r", stdin);// freopen("out.txt", "w", stdout);int n,x;cin>>n;mem();for(int i=1; i<=n; i++) {while(cin>>x&&x!=0) {G[i].push_back(x);}}for(int i=1; i<=n; i++) {             //可能图不连通 if(!vis[i]) {tarjan(i);}}for(int i=1; i<=n; i++) {                   //求入度和出度 for(int j=0; j<G[i].size(); j++) {if(id[i]!=id[G[i][j]]) {rd[id[G[i][j]]]++;cd[id[i]]++;}}}int ansA=0,ansB=0;                       //入度为0的个数,出度为0的个数 for(int i=1; i<=max_num; i++) {if(rd[i]==0)ansA++;if(cd[i]==0)ansB++;}if(max_num==1)                         //只有一个强连通分量 cout<<1<<endl<<0<<endl;elsecout<<ansA<<endl<<max(ansA,ansB)<<endl;return 0;}

原创粉丝点击