poj 1236 强联通分量
Posted 缄默火
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了poj 1236 强联通分量相关的知识,希望对你有一定的参考价值。
大致题意给你有一个点数为n<=100的有向图。
求解两个子任务:
1:最少给多少个点信息,这些点的信息可以顺着有向边传遍全图。
2:最少要加多少条边,使得整个图强联通。
求强联通分量再缩点后得到一个有向无环图。
设其入度为0的点数为t1,出度为0的点数为t2
1的答案即为强联通缩点之后入度为0的点的数量t1。
2的答案即为max(t1,t2).
注意一个特殊情况:若缩点后只有一个点了(即原图便是强联通的)此时t1=1,t2=1但是第二个任务的答案应当是0。
AC代码:
#include<cstdio> #include<cmath> #include<cstring> #include<iostream> #define rep(i,a,b) for(int i=a;i<=b;++i) using namespace std; const int MAXN=110; int n,cnt; int graph[MAXN][MAXN]; int DFN[MAXN],low[MAXN],Stap[MAXN],label[MAXN]; bool instake[MAXN]; int Stop,Bcnt; int adjm[MAXN][MAXN]; int in[MAXN],out[MAXN]; void init() { memset(graph,0,sizeof(graph)); memset(DFN,0,sizeof(DFN)); memset(in,0,sizeof(in)); memset(out,0,sizeof(out)); memset(adjm,0,sizeof(adjm)); memset(instake,0,sizeof(instake)); int t; cnt=0;Stop=0;Bcnt=0; rep(i,1,n) { while(scanf("%d",&t)==1&&t) { graph[i][++graph[i][0]]=t; } } } void tarjan(int u) { DFN[u]=low[u]=++cnt; instake[u]=1; Stap[++Stop]=u; rep(i,1,graph[u][0]) { int v=graph[u][i]; if(!DFN[v]) { tarjan(v); if(low[v]<low[u]) low[u]=low[v]; } else if(instake[v]&&DFN[v]<low[u]) low[u]=DFN[v]; } int j; if(DFN[u]==low[u]) { ++Bcnt; do { j=Stap[Stop--]; instake[j]=0; label[j]=Bcnt; }while(j!=u); } } int main() { //freopen("in.txt","r",stdin); while(scanf("%d",&n)==1) { init(); rep(i,1,n) { if(!DFN[i]) tarjan(i); } if(Bcnt==1) { printf("1\n0\n");continue; } rep(i,1,n) { rep(j,1,graph[i][0]) { int v=graph[i][j]; if(label[i]!=label[v]) { out[label[i]]++; in[label[v]]++; } } } int t1=0,t2=0; rep(i,1,Bcnt) { if(in[i]==0) t1++; if(out[i]==0) t2++; } printf("%d\n%d\n",t1,max(t1,t2)); } return 0; }
以上是关于poj 1236 强联通分量的主要内容,如果未能解决你的问题,请参考以下文章
POJ1236Network of Schools(强连通分量 + 缩点)