Network of Schools POJ
来源:互联网 发布:马云否认淘宝是日本的 编辑:程序博客网 时间:2024/05/29 13:17
tarjan强连通分量
题意:
N(2<N<100
)各学校之间有单向的网络,每个学校得到一套软件后,可以通过单向网络向周边的学校传输,问题1:初始至少需要向多少个学校发放软件,使得网络内所有的学校最终都能得到软件。2,至少需要添加几条传输线路(边),使任意向一个学校发放软件后,经过若干次传送,网络内所有的学校最终都能得到软件。
思路
也就是:
— 给定一个有向图,求:
1) 至少要选几个顶点,才能做到从这些顶点出发,可以到达全部顶点
2) 至少要加多少条边,才能使得从任何一个顶点出发,都能到达全部顶点
解法
1. 求出所有强连通分量
2. 每个强连通分量缩成一点,则形成一个有向无环图DAG。
3. DAG上面有多少个入度为0的顶点,问题1的答案就是多少
4.在DAG上要加几条边,才能使得DAG变成强连通的,问题2的答案就是多少
设ans1入度为零的定点数,ans2出度为零的顶点数
加边条数是max(ans1,ans2);
此外:当只有一个强连通分支的时候,就是缩点后只有一个点,虽然入度出度为0的都有一个,但是实际上不需要增加清单的项了,所以答案是1,0;
代码
/* * Author : Echo * Email : 1666424499@qq.com * Description : * Created Time : 2017/10/10 19:25:26 * Last Modify : 2017/10/15 16:03:40 * File Name : \yanga11ang\write.cpp */#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>#include <string>#include <queue>using namespace std;const int maxn=110;const int maxm=1e4+100;const int INF=1e9;struct edge { int to,next;}an[maxm];int head[maxn];int dfn[maxn]; //入栈时间戳int ins[maxn]; //是否入栈int low[maxn]; //最早发现时间int stk[maxn]; //手工栈int dot[maxn]; //缩点int ind[maxn]; //入度int out[maxn]; //出度int m=0;//edge int top;//stackint cnt;//dotint n;//pointint tm;//timevoid addedge(int u,int v){ an[++m].to=v; an[m].next=head[u]; head[u]=m;}void tarjan(int u){ dfn[u]=low[u]=++tm; stk[++top]=u; ins[u]=1; for(int i=head[u];i!=-1;i=an[i].next){ int v=an[i].to; if(dfn[v]==0){ tarjan(v); if(low[u]>low[v]) low[u]=low[v]; } else if(ins[v]&&low[u]>low[v]){ low[u]=low[v]; } } if(low[u]!=dfn[u]) return; int v=stk[top--]; ins[v]=0; dot[v]=++cnt; while(u!=v){ v=stk[top--]; ins[v]=0; dot[v]=cnt; }}int main(){ cin>>n; m=top=cnt=tm=0; for(int i=1;i<=n;i++){ dfn[i]=ins[i]=ind[i]=out[i]=0; head[i]=-1; } for(int i=1;i<=n;i++){ int j; while(scanf("%d",&j)&&j){ addedge(i,j); } } for(int i=1;i<=n;i++){ if(dfn[i]) continue; tarjan(i); } for(int u=1;u<=n;u++){ for(int i=head[u];i!=-1;i=an[i].next){ int v=an[i].to; if(dot[u]==dot[v])continue; out[dot[u]]++; ind[dot[v]]++; } } int ans1=0,ans2=0; for(int i=1;i<=cnt;i++){ if(ind[i]==0) ans1++; if(out[i]==0) ans2++; } if(cnt==1)printf("1\n0\n"); else printf("%d\n%d\n",ans1,ans1>ans2? ans1:ans2); return 0;}
阅读全文
0 0
- poj Network of Schools
- Network of Schools POJ
- Network of Schools POJ
- Network of Schools POJ
- POJ 1236 Network of Schools
- POJ 1236 Network of Schools
- poj 1236 Network of Schools
- POJ 1236 Network of Schools
- POJ 1236 Network of Schools
- poj 1236 Network of Schools
- poj 1236 Network of Schools
- poj 1206 Network of Schools
- POJ 1236 Network of Schools
- POJ-1236-Network of Schools
- POJ 1236 Network of Schools
- POJ 1236 Network of Schools
- poj 1236 Network of Schools
- poj 1236 Network of Schools
- 课堂练习5(第四周)
- 28.leetCode647:Palindromic Substrings
- Java中几个常用设计模式
- 27、C#里面组合框ComboBox的属性和事件
- Javascript生成全局唯一标识符(GUID,UUID)的方法
- Network of Schools POJ
- js实现每次调用一个函数自动加1
- poj 2560 Freckles(并查集)
- redis bitmap的秘密
- 【Linux命令】scp传输文件
- 编程序找出1000之内的所有完数,并按下面格式输出其因子:6 its factors are 1,2,3
- JAVA知识点整理第六部分——线程
- Unity3D-在移动端显示Debug信息
- ubuntu apach2 配置