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
0
");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
%d
",t1,max(t1,t2));
    }
    return 0;
}
原文地址:https://www.cnblogs.com/zhixingr/p/7822422.html