您的位置:首页 > 其它

poj 1236 Network of Schools (强联通分量+缩点)

2015-03-31 20:12 501 查看
题意:

给出多个学校的网络图,每个学校多有一个表,表中存这个学校能联通的学校编号(单向联通)。两个问题:1、至少要多少分资料才能全部传到所有学校;2、至少要连多少条边才能使得整个整个网络联通。

题解:

强联通,缩点完,根据缩点判断入度为0的点的个数ansA,出度为0的点的个数ansB。乱搞能发现两个问题的答案分别是ansA,max(ansA,ansB)

#include<iostream>
#include<math.h>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<vector>
#include<queue>
#include<map>
#include<set>
using namespace std;
#define B(x) (1<<(x))
typedef long long ll;
void cmax(int& a,int b){ if(b>a)a=b; }
void cmin(int& a,int b){ if(b<a)a=b; }
const int oo=0x3f3f3f3f;
const int MOD=1000000007;
const int maxn=105;
const int maxm=11000;
struct EDGE{
    int v,next,c,f;
}E[maxm];
int head[maxn],tol;
int low[maxn],dfn[maxn],instack[maxn],Stack[maxn],id[maxn];
int ind[maxn],outd[maxn];
int g_cnt,top,ID;
int ans[maxn];
struct Node{
    int n;
    Node(int x){ n=x; }
    bool operator<(const Node& a)const{
        return a.n<n;
    }
};

void Init(){
    memset(head,-1,sizeof head);
    tol=0;
    memset(low,0,sizeof low);
    memset(dfn,0,sizeof dfn);
    memset(instack,0,sizeof instack);
    g_cnt=top=ID=0;
}

void add_edge(int u,int v){
    E[tol].v=v;
    E[tol].next=head[u];
    head[u]=tol++;
}

void Tarjan(int u){
    dfn[u]=low[u]=++g_cnt;
    Stack[++top]=u;
    instack[u]=1;
    int v;
    for(int i=head[u];i!=-1;i=E[i].next){
        v=E[i].v;
        if(!dfn[v]){
            Tarjan(v);
            if(low[v]<low[u])
                low[u]=low[v];
        }else if(instack[v]&&dfn[v]<low[u])
            low[u]=dfn[v];
    }
    if(dfn[u]==low[u]){
        ID++;
        do{
            v=Stack[top--];
            instack[v]=0;
            id[v]=ID;
        }while(u!=v);
    }
}

void gao(int n){
    memset(ind,0,sizeof ind);
    memset(outd,0,sizeof outd);
    for(int i=1;i<=n;i++){
        int u=i;
        for(int j=head[u];j!=-1;j=E[j].next){
            int v=E[j].v;
            if(id[u]!=id[v]){
                ind[id[v]]++;
                outd[id[u]]++;
            }
        }
    }
    if(ID==1){
        printf("1\n0\n");
        return ;
    }
    int ansA=0,ansB=0;
    for(int i=1;i<=ID;i++){
        if(ind[i]==0)ansA++;
        if(outd[i]==0)ansB++;
    }
    printf("%d\n%d\n",ansA,max(ansA,ansB));
}

int main(){
    //freopen("E:\\read.txt","r",stdin);
    int n,u,v;
    while(scanf("%d",&n)!=EOF){
        Init();
        for(int i=1;i<=n;i++){
            u=i;
            while(scanf("%d",&v)){
                if(v==0)break;
                add_edge(u,v);
            }
        }
        for(int i=1;i<=n;i++)
            if(!dfn[i])
                Tarjan(i);
        gao(n);
    }
    return 0;
}
/*
4
2 1 2
2 1 2
2 2 3
2 3 4
1 2 3 4
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: