poj1236 Network of Schools【强连通分量(tarjan)缩点】

转载请注明出处,谢谢:http://www.cnblogs.com/KirisameMarisa/p/4316263.html  ---by 墨染之樱花

【题目链接】http://poj.org/problem?id=1236

【题目描述】给一张有向图,表示学校通信网络,边<u,v>代表信息可以由u传递到v。现要完成两个任务:1、求最少把几个点作为信息传递的起点就能让信息转达到所有节点 2、最少在添加几条边就能使任意两点间可达(构造强连通分量)

【思路】先利用tarjan缩点使整个图化为DAG新图(有关tarjan的详细资料请戳:https://www.byvoid.com/blog/scc-tarjan/)。

任务一:如果一个点没有入度,那就表示其他点是不可能到达它的,所以该点只能作为一个起点。那么任务一就是等价于求新图中入度为0的点的个数。

任务二:在DAG中从一个没有入度的点(点1)出发,不断地延伸,延伸到一个没有出度的点(点2)时才会停止,此时将点2与点1连接,那么这条路径就会变成一个环,路径各个点就会互相可达。对于整个图来说只要找出所有没入度的点和没出度的点并将它们一一连接就行了,保证每个点都有出度和入度。所以任务二等价于求新图中入度为0的点个数与出度为0的点个数的最大值

#include <vector>
#include <cstdio>
#include <cstring>
using namespace std;
#define MAXN 110
#define PB(X) push_back(X)
#define REP(X,N) for(int X=0;X<N;X++)
#define CLR(A,X) memset(A,X,sizeof(A))
typedef vector<int> VI;

int V,nV;
VI G[MAXN],nG[MAXN];
int low[MAXN],dfn[MAXN],st[MAXN],belong[MAXN];
int top,cnt,index;
bool inst[MAXN];
int ind[MAXN],outd[MAXN];

void init()
{
    top=cnt=index=0;
    CLR(dfn,0);
    CLR(ind,0);CLR(dfn,0);
}

void tarjan(int u)
{
    low[u]=dfn[u]=++index;
    st[top++]=u;
    inst[u]=1;
    REP(i,G[u].size())
    {
        int v=G[u][i];
        if(!dfn[v])
        {
            tarjan(v);
            if(low[v]<low[u])
                low[u]=low[v];
        }
        else if(inst[v] && dfn[v]<low[u])
            low[u]=dfn[v];
    }
    int j;
    if(low[u]==dfn[u])
    {
        cnt++;
        do
        {
            j=st[--top];
            inst[j]=0;
            belong[j]=cnt-1;
        }while(j!=u);
    }
}

int main()
{
    init();
    scanf("%d",&V);
    REP(i,V)
    {
        int x;
        while(scanf("%d",&x))
        {
            if(x==0)
                break;
            x--;
            G[i].PB(x);
        }
    }
    REP(i,V)
        if(!dfn[i])
            tarjan(i);
    nV=cnt;
    if(nV==1)
    {
        printf("1\n0\n");
        return 0;
    }
    REP(i,V)
    {
        REP(j,G[i].size())
        {
            int x=belong[i],y=belong[G[i][j]];
            if(x!=y)
            {
                nG[x].PB(y);
                ind[y]++;outd[x]++;
            }
        }
    }
    int noInd=0,noOutd=0;
    REP(i,nV)
    {
        if(!ind[i])
            noInd++;
        if(!outd[i])
            noOutd++;
    }
    printf("%d\n%d\n",noInd,max(noInd,noOutd));
    return 0;
}

时间: 2024-08-29 01:40:43

poj1236 Network of Schools【强连通分量(tarjan)缩点】的相关文章

POJ1236 Network of Schools (强连通分量,注意边界)

A number of schools are connected to a computer network. Agreements have been developed among those schools: each school maintains a list of schools to which it distributes software (the “receiving schools”). Note that if B is in the distribution lis

Network of Schools(强连通分量+缩点) (问添加几个点最少点是所有点连接+添加最少边使图强连通)

Network of Schools Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 13801   Accepted: 5505 Description A number of schools are connected to a computer network. Agreements have been developed among those schools: each school maintains a li

[IOI1996] USACO Section 5.3 Network of Schools(强连通分量)

nocow上的题解很好. http://www.nocow.cn/index.php/USACO/schlnet 如何求强连通分量呢?对于此题,可以直接先用floyd,然后再判断. ---------------------------------------------------------------------------------- #include<cstdio> #include<iostream> #include<algorithm> #includ

强连通分量tarjan缩点——POJ2186 Popular Cows

这里的Tarjan是基于DFS,用于求有向图的强联通分量. 运用了一个点dfn时间戳和low的关系巧妙地判断出一个强联通分量,从而实现一次DFS即可求出所有的强联通分量. §有向图中, u可达v不一定意味着v可达u.    相互可达则属于同一个强连通分量    (Strongly Connected Component, SCC) §有向图和它的转置的强连通分量相同 §所有SCC构成一个DAG(有向无环图) dfn[u]为节点u搜索的次序编号(时间戳),即首次访问u的时间 low[u]为u或u的

POJ 1236(强连通分量/Tarjan缩点)

传送门 Description A number of schools are connected to a computer network. Agreements have been developed among those schools: each school maintains a list of schools to which it distributes software (the “receiving schools”). Note that if B is in the

POJ - 1236 Network of Schools(强连通分量)

题目大意:有N个点,接着给出N个点所能连接的点. 问题1:如果要将一个信息传递给这N个点,至少需要传递给多少个点,然后让这些点进行传播,使N个点都得到信息 问题2:需要添加多少条边才能使这N个点能两两连通 解题思路:求出所有的强连通分量,接着缩点,再以桥为路径,建图 找出这张图中入度为0的,因为只有入度为0的才需要进行通知,其他的点可以通过其他边进行传达 需要添加多少个点,观察这张图,求出每个点的出度和入度,取max(入度为零的点的数量,出度为0的点数量) 注意当强连通分量只有1个的时候 #in

[强连通分量+Tarjan缩点]

强连通分量 定义:有向图强连通分量:在有向图G中,如果两个顶点vi,vj间(vi>vj)有一条从vi到vj的有向路径,同时还有一条从vj到vi的有向路径,则称两个顶点强连通(strongly connected).如果有向图G的每两个顶点都强连通,称G是一个强连通图.有向图的极大强连通子图,称为强连通分量(strongly connected components). Tarjan 是 一种基于 dfs 的算法 ,图中每个强连通分量为搜索树的一棵子树 搜索时,把当前搜索树中未处理的节点加入一个堆

POJ 1236 Network of Schools (强连通分量缩点求度数)

题意: 求一个有向图中: (1)要选几个点才能把的点走遍 (2)要添加多少条边使得整个图强联通 分析: 对于问题1, 我们只要求出缩点后的图有多少个入度为0的scc就好, 因为有入度的scc可以从其他地方到达. 对于问题2, 每个入度为0的scc, 都可以补一条边可以变成强连通图, 每个出度为0的scc, 也可以补一条边使其变成强连通图. 所以答案就是max(入度为0scc个数,出度为0scc个数). #include<cstdio> #include<iostream> #inc

POJ 1236 Network of Schools(强连通分量)

题目地址:POJ 1236 这个题的大意是求最少往多少点发送消息可以使任意一个点都能收到消息和最少增加多少条边可以使图为连通图.对于第一个问题,可以求入度为0的强连通块的块数,因为只有入度为0的强连通块是无法从外界接受信息的,而只要有一个入度的话,那整个连通块就都可以接收到信息.第二个问题则是求入度为0的强连通块与出度为0的强连通块的个数的最大值. 代码如下: #include <iostream> #include <cstdio> #include <string>

POJ 1236 Network Of Schools (强连通分量模板题)

代码: #include<iostream> #include<cstdio> #include<cmath> #include<map> #include<queue> #include<vector> #include<cstring> #include<algorithm> #define rep(i,a,b) for(int i=(a);i<(b);i++) #define rev(i,a,b)