【强连通分量】POJ 1236 Network of Schools
2017-03-10 09:13
274 查看
题目链接:http://poj.org/problem?id=1236
题目大意:N(2<N<100)各学校之间有单向的网络,每个学校得到一套软件后,可以通过单向网络向周边的学校传输,问题1:初始至少需要向多少个学校发放软件,使得网络内所有的学校最终都能得到软件。2,至少需要添加几条传输线路(边),使任意向一个学校发放软件后,经过若干次传送,网络内所有的学校最终都能得到软件。
也就是: 给定一个有向图,求:
1) 至少要选几个顶点,才能做到从这些顶点出发,可以到达全部顶点
2) 至少要加多少条边,才能使得从任何一个顶点出发,都能到达全部顶点
分析:首先找出强连通分量,然后把每个强连通分量缩成一个点,得到一个DAG。接下来,设有a个结点(别忘了,这里的每个结点对应于原图的一个强连通分量)入度为0,b个结点的出度为0,则max(a,b)就是2的答案(注意特殊情况:当原图已是强连通时,答案是0而不是1),a为1的答案。
加边的方法:
要为每个入度为0的点添加入边,为每个出度为0的点添加出边
若 m <= n,则加了这n条边后,已经没有入度0点,则问题解决,一共加了n条边
若 m > n,则还有m-n个入度0点,则从这些点以外任取一点,和这些点都连上边,即可,这还需加m-n条边。
所以,max(m,n)就是第二个问题的解
Code:(仅供参考)
题目大意:N(2<N<100)各学校之间有单向的网络,每个学校得到一套软件后,可以通过单向网络向周边的学校传输,问题1:初始至少需要向多少个学校发放软件,使得网络内所有的学校最终都能得到软件。2,至少需要添加几条传输线路(边),使任意向一个学校发放软件后,经过若干次传送,网络内所有的学校最终都能得到软件。
也就是: 给定一个有向图,求:
1) 至少要选几个顶点,才能做到从这些顶点出发,可以到达全部顶点
2) 至少要加多少条边,才能使得从任何一个顶点出发,都能到达全部顶点
分析:首先找出强连通分量,然后把每个强连通分量缩成一个点,得到一个DAG。接下来,设有a个结点(别忘了,这里的每个结点对应于原图的一个强连通分量)入度为0,b个结点的出度为0,则max(a,b)就是2的答案(注意特殊情况:当原图已是强连通时,答案是0而不是1),a为1的答案。
加边的方法:
要为每个入度为0的点添加入边,为每个出度为0的点添加出边
若 m <= n,则加了这n条边后,已经没有入度0点,则问题解决,一共加了n条边
若 m > n,则还有m-n个入度0点,则从这些点以外任取一点,和这些点都连上边,即可,这还需加m-n条边。
所以,max(m,n)就是第二个问题的解
Code:(仅供参考)
/*割点和桥*/ #include<stdio.h> #include<algorithm> #include<iostream> #include<string.h> #include<math.h> #include<queue> #include<map> #include<set> #include<stack> #include<stdlib.h> using namespace std; typedef long long LL; const int maxn=210;//点的个数 const int maxm=5010;//边的个数 int low[maxn],dfn[maxn],head[maxn],sccno[maxn]; int tot,Index,scc; stack<int>s; struct edge { int to,next; } eg[maxm]; void addedge(int u,int v) { eg[tot].to=v; eg[tot].next=head[u]; head[u]=tot++; } void Tarjan(int u) { low[u]=dfn[u]=++Index; s.push(u); for(int i=head[u]; i!=-1; i=eg[i].next) { int v=eg[i].to; if(!dfn[v]) { Tarjan(v); low[u]=min(low[u],low[v]); } else if(!sccno[v]) low[u]=min(low[u],dfn[v]); } if(low[u]==dfn[u]) { scc++;//强连通分量的个数 for(;;) { int x=s.top(); s.pop(); sccno[x]=scc;//每个点属于哪一个强连通分量 if(x==u) break; } } } void init()//初始化 { while(!s.empty()) s.pop(); tot=0,Index=0,scc=0; memset(head,-1,sizeof(head)); memset(sccno,0,sizeof(sccno)); memset(low,0,sizeof(low)); memset(dfn,0,sizeof(dfn)); } int in[maxn],out[maxn]; int main() { int n,x; scanf("%d",&n); init(); memset(in,0,sizeof(in)); memset(out,0,sizeof(out)); for(int i=1; i<=n; i++) { while(~scanf("%d",&x)&&x) addedge(i,x); } for(int i=1; i<=n; i++) { if(!dfn[i]) Tarjan(i); } for(int u=1;u<=n;u++) { for(int i=head[u];i!=-1;i=eg[i].next) { int v=eg[i].to; if(sccno[u]!=sccno[v]) { in[sccno[v]]++;//入度 out[sccno[u]]++;//出度 } } } int ans1=0,ans2=0; for(int i=1;i<=scc;i++) { if(!in[i]) ans1++;//入度为0的点的个数 if(!out[i]) ans2++;//出度为0的点的个数 } int ans=max(ans1,ans2); if(scc==1)//注意 ans=0; printf("%d\n%d\n",ans1,ans); }
相关文章推荐
- |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 (强连通分量[Tarjan])
- 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 1236 Network of Schools (强连通分量,块,缩点)
- POJ - 1236 Network of Schools (强连通分量)
- 【强连通分量模板题 && 加几条边变强连通】POJ - 1236 Network of Schools
- poj 1236 Network of Schools(强连通分量 Tarjan算法)
- POJ - 1236 Network of Schools(有向图的强连通分量)
- 【POJ 1236】Network of Schools(强连通分量_tarjan)
- poj 1236 Network of Schools 强连通分量