首页 > 其他分享 >POJ2762(判断无向图的弱连通)

POJ2762(判断无向图的弱连通)

时间:2023-05-31 16:32:11浏览次数:46  
标签:连通 int memset 无向 POJ2762 dfn Edge sizeof low


题目:http://poj.org/problem?id=2762

 

题意:给出n个山洞,对于每个山洞,如果任意选择两点s,e,都满足s可以到达e或者e可以到达s,则输出Yes,否则输出No。

 

分析:实际上判断是否弱连通,所以首先强连通,然后缩点,对缩点形成的图最多只能有一个入度为0的点,如果有多个入度为

0的点,则这两个连通分量肯定是不连通的。缩点后形成的图形是一棵树,入度为0的点是这颗树的根,这棵树只能是单链,不

能有分叉,如果有分叉,则这些分叉之间是不可达的,所以就对这棵树进行DFS,如果是单链则是YES。

 

#include <iostream>
#include <string.h>
#include <stdio.h>

using namespace std;
const int N = 10005;

struct Edge
{
    int to;
    Edge *next;
};

Edge *map1[N],*map2[N];  //分别保存原图和缩点后的图
int dfn[N],low[N],stack[N],belong[N],indeg[N];
int index,scc_num,top;
bool tmp[N];
int result[N];

void Tarjan(int u)
{
    dfn[u] = low[u] = ++index;
    stack[++top] = u;
    tmp[u] = true;
    for(Edge *p = map1[u]; p; p = p->next) //枚举每一条边
    {
        int v = p->to;
        if(!dfn[v])
        {
            Tarjan(v);  //dfs继续下找
            low[u] = min(low[u],low[v]);
        }
        else if(tmp[v])
        {
            low[u] = min(low[u],dfn[v]);
        }
    }
    if(low[u] == dfn[u]) //如果节点u是强连通分量的根
    {
        int t;
        ++scc_num;  //强连通分量个数加1
        do
        {
            t = stack[top--];
            tmp[t] = false;
            belong[t] = scc_num;  //记录属于第几个强连通分量
        }
        while(t != u);
    }
}

int Count(int n)
{
    for(int i=1;i<=n;i++)
        if(!dfn[i])
           Tarjan(i);
    return scc_num;
}

int Find() //在新图中找入度为0的点,如果只有一个就返回位置,否则返回0
{
    int record;
    int cnt = 0;
    for(int i=1; i<=scc_num; i++)
    {
        if(indeg[i] == 0)
        {
            cnt++;
            record = i;
        }
    }
    if(cnt == 1) return record;
    return 0;
}

bool TopSort()
{
    int u,num = 0;
    while(u = Find())
    {
        result[num++] = u;
        indeg[u] = -1;
        Edge *p = map2[u];
        while(p)
        {
            indeg[p->to]--;
            p = p->next;
        }
    }
    if(num == scc_num) return true;
    return false;
}

void Init()
{
    index = 0;
    top = 0;
    scc_num = 0;
    memset(dfn,0,sizeof(dfn));
    memset(low,0,sizeof(low));
    memset(indeg,0,sizeof(indeg));
    memset(tmp,false,sizeof(tmp));
    memset(map1,NULL,sizeof(map1));
    memset(map2,NULL,sizeof(map2));
    memset(result,0,sizeof(result));
}

int main()
{
    int T,m,n;
    scanf("%d",&T);
    while(T--)
    {
        Init();
        scanf("%d%d",&n,&m);
        while(m--)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            Edge *p = new Edge();
            p->to = b;
            p->next = map1[a];
            map1[a] = p;
        }
        int cnt = Count(n);
        if(cnt == 1)
        {
            puts("Yes");
            continue;
        }
        for(int i=1;i<=n;i++)
        {
            Edge *p = map1[i];
            while(p)
            {
                if(belong[i] != belong[p->to])
                {
                    indeg[belong[p->to]]++;
                    Edge *q = new Edge();
                    q->to = belong[p->to];
                    q->next = map2[belong[i]];
                    map2[belong[i]] = q;
                }
                p = p->next;
            }
        }
        bool flag = false;
        int ans = 0;
        for(int i=1;i<=cnt;i++)
        {
            if(indeg[i] == 0)
               ans++;
        }
        if(ans > 1) flag = false;
        else if(TopSort()) flag = true;
        if(flag) puts("Yes");
        else     puts("No");
    }
    return 0;
}

 

标签:连通,int,memset,无向,POJ2762,dfn,Edge,sizeof,low
From: https://blog.51cto.com/u_16146153/6388134

相关文章

  • [2020集训队论文] 最小连通块
    这是一道交互题。交互库里有一棵$n$个点的树,你可以通过做若干次如下询问来确定这棵树:给定一个节点集合$S$和节点$x$,交互库会告诉你$x$是否在包含$S$的最小连通块中。Details具体的,你需要引用头文件D.h并且实现以下函数:std::vector<std::pair<int,int>>work(int......
  • P1790 小胡同学的连通图
    #include<cstdio>#include<iostream>#include<cstring>#include<algorithm>#include<vector>usingnamespacestd;intpar[105]={0};intrank0[105]={0};introot[105]={0};voidinit(intn){for(inti=1;i......
  • POJ1737 Connected Graph ( n点无向连通图计数
    题意说明:求\(n\)个点的无向连通图个数据说已经非常典了,但是我太菜了不会组合数学,最近补档时看到这道题,决定记录下来理理思路......
  • 测试远程端口是否连通
    telnetipportssh-v-pportipcurlip:portwgetip:portlinux检测端口命令linux测试端口命令(linux测试端口命令有哪些)......
  • 2023-05-12:存在一个由 n 个节点组成的无向连通图,图中的节点按从 0 到 n - 1 编号, 给你
    2023-05-12:存在一个由n个节点组成的无向连通图,图中的节点按从0到n-1编号,给你一个数组graph表示这个图,其中,graph[i]是一个列表,由所有与节点i直接相连的节点组成。返回能够访问所有节点的最短路径的长度。你可以在任一节点开始和停止,也可以多次重访节点,并且可以重......
  • hdu 1599 find the mincost route(无向图的最小环:求从一个点遍历所有节点以后回到原点
    题目:findthemincostrouteTimeLimit:1000/2000MS(Java/Others)    MemoryLimit:32768/32768K(Java/Others)TotalSubmission(s):2801    AcceptedSubmission(s):1115ProblemDescription杭州有N个景区,景区之间有一些双向的路来连接,现在8600想找一条旅游......
  • 「学习笔记」双连通分量、割点与桥
    文章图片全部来自Oi-wiki,部分图片加以修改前面我们在学tarjan算法时,提到过强连通分量,即有向图上的环,那么无向图上是否也有强连通分量呢?很遗憾,没有但是,无向图有双连通分量!分为点双连通和边双连通(下面简称点双和边双)。边双连通分量概念在一张联通的无向图中,对于两个点\(x......
  • 2023-05-05:给定一个无向、连通的树 树中有 n 个标记为 0...n-1 的节点以及 n-1 条边
    2023-05-05:给定一个无向、连通的树树中有n个标记为0...n-1的节点以及n-1条边。给定整数n和数组edges,edges[i]=[ai,bi]表示树中的节点ai和bi之间有一条边。返回长度为n的数组answer,其中answer[i]:树中第i个节点与所有其他节点之间的距离之和。输入......
  • Ansible-受控主机配置并测试连通性
    1.Ansible配置文件[root@masterhome]#ansible--versionansible2.9.27configfile=/etc/ansible/ansible.cfgconfiguredmodulesearchpath=[u'/root/.ansible/plugins/modules',u'/usr/share/ansible/plugins/modules']ansiblepython......
  • 12.石油储备(简单搜索 DFS/BFS 统计连通块个数)
    石油储备题目一片土地可以看作是一个\(n\)行\(m\)列的方格矩阵。其中一些方格藏有石油,用@表示,其余方格没有石油,用*表示。每个方格都与其上、下、左、右、左上、右上、左下、右下八个方格视为相邻。如果两个藏有石油的方格相邻,则它们被认为是处于同一片油田,否则它们被......