【Tarjan重新建图】POJ - 1236 - Network of Schools

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/monochrome00/article/details/81783459

题目链接<http://poj.org/problem?id=1236>


题意:

n个学校,学校之间被单向边连接。有两个问题:

1、要给几个学校软件,才能让所有学校都能收到。

2、至少要加几条边,才能使原图变成强连通图。

题目保证给出的图是一个连通图。


题解:

Tarjan缩点,重新构图。

入度为零的个数就是第一问的答案。

max(入度为零,出度为零)是第二问的答案。

另外注意,如果本身就是强连通图,那么答案就是1,0了,这个要特判一下。


#include<iostream>
#include<cstdio>
#include<string.h>
#include<string>
#include<algorithm>
#include<stack>
using namespace std;
const int N=105;
int n;
struct Edge{
    int u,v,w,nxt;
    Edge(int u=0,int v=0,int w=0,int nxt=0):u(u),v(v),w(w),nxt(nxt){}
}edge[N*N],e[N*N];

int p[N],edn;
void add(int u,int v,int w){
    edge[++edn]=Edge(u,v,w,p[u]);p[u]=edn;
}
int hd[N],en;
void ad(int u,int v,int w){
    e[++en]=Edge(u,v,w,hd[u]);hd[u]=en;
}

int dfn[N],low[N],st[N],scc[N],index,top,sccnum;
void tarjan(int u){
    dfn[u]=low[u]=++index;
    st[++top]=u;
    for(int i=p[u];~i;i=edge[i].nxt){
        int v=edge[i].v;
        if(!dfn[v]){
            tarjan(v);
            low[u]=min(low[u],low[v]);
        }
        else if(!scc[v]) low[u]=min(low[u],dfn[v]);
    }
    if(low[u]==dfn[u]){
        sccnum++;
        while(1){
            int x=st[top--];
            scc[x]=sccnum;
            if(x==u) break;
        }
    }
}
int in[N],out[N];
void rebuild(){
    for(int x=1;x<=n;x++){
        int u=scc[x];
        for(int i=p[x];~i;i=edge[i].nxt){
            int y=edge[i].v;
            int v=scc[y];
            if(u==v) continue;
            ad(u,v,1);
            in[v]++;out[u]++;
        }
    }
}
int main(){
    int x;
    scanf("%d",&n);
    memset(p,-1,sizeof(p));edn=-1;
    memset(hd,-1,sizeof(hd));en=-1;
    for(int i=1;i<=n;i++){
        while(scanf("%d",&x)){
            if(x==0) break;
            add(i,x,1);
        }
    }
    for(int i=1;i<=n;i++){
        if(!scc[i]) tarjan(i);
    }
    rebuild();
    int iz=0,oz=0;
    for(int i=1;i<=sccnum;i++){
        if(in[i]==0) iz++;
        if(out[i]==0) oz++;
    }
    if(sccnum==1) printf("1\n0\n");
    else printf("%d\n%d\n",iz,max(iz,oz));
}

猜你喜欢

转载自blog.csdn.net/monochrome00/article/details/81783459