1. 程式人生 > >poj 1236 強聯通分量

poj 1236 強聯通分量

label 題意 -- stop continue 1=1 特殊情況 pac ostream

大致題意給你有一個點數為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 強聯通分量