標籤:cst style log define can string init ++i tap
大致題意給你有一個點數為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 強聯通分量