51nod 1076 2条不相交的路径 无向图强联通分量 trajan算法

1076 2条不相交的路径

基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题

 收藏

 关注

给出一个无向图G的顶点V和边E。进行Q次查询,查询从G的某个顶点V[s]到另一个顶点V[t],是否存在2条不相交的路径。(两条路径不经过相同的边)

(注,无向图中不存在重边,也就是说确定起点和终点,他们之间最多只有1条路)

Input

第1行:2个数M N,中间用空格分开,M是顶点的数量,N是边的数量。(2 <= M <= 25000, 1 <= N <= 50000)
第2 - N + 1行,每行2个数,中间用空格分隔,分别是N条边的起点和终点的编号。例如2 4表示起点为2,终点为4,由于是无向图,所以从4到2也是可行的路径。
第N + 2行,一个数Q,表示后面将进行Q次查询。(1 <= Q <= 50000)
第N + 3 - N + 2 + Q行,每行2个数s, t,中间用空格分隔,表示查询的起点和终点。

Output

共Q行,如果从s到t存在2条不相交的路径则输出Yes,否则输出No。

Input示例

4 4
1 2
2 3
1 3
1 4
5
1 2
2 3
3 1
2 4
1 4

Output示例

Yes
Yes
Yes
No
No

直接构图套强联通分量的模板  然后看询问的两个点是否联通一开始数组开小了 然后最后3个答案一直WA找了半天简直毒瘤啊...
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <vector>
#include <iomanip>
#include <math.h>
#include <map>
using namespace std;
#define FIN     freopen("input.txt","r",stdin);
#define FOUT    freopen("output.txt","w",stdout);
#define INF     0x3f3f3f3f
#define INFLL   0x3f3f3f3f3f3f3f
#define lson    l,m,rt<<1
#define rson    m+1,r,rt<<1|1
typedef long long LL;
typedef pair<int, int> PII;
using namespace std;

const int MX = 1e5 + 10;

struct Edge {
    int u, v, nxt;
} E[MX];
int Head[MX], erear;
void edge_init() {
    erear = 0;
    memset(Head, -1, sizeof(Head));
}
void edge_add(int u, int v) {
    E[erear].u = u;
    E[erear].v = v;
    E[erear].nxt = Head[u];
    Head[u] = erear++;
}
int n, m, IN[MX], cnt[MX], val[MX];
int bsz, ssz, dsz;
int Low[MX], DFN[MX];
void Init_tarjan(int n) {
    bsz = ssz = dsz = 0;
    for(int i = 1; i <= n; ++i) Low[i] = DFN[i] = 0;
}

int Stack[MX], inStack[MX], Belong[MX];
void trajan(int u, int e) {
    inStack[u] = 1;
    Stack[++ssz] = u;
    DFN[u] = Low[u] = ++dsz;
    for(int i = Head[u]; ~i; i = E[i].nxt) {
        int v = E[i].v;
        if((i ^ 1) == e) continue;
        if(!DFN[v]) {
            trajan(v, i);
            Low[u] = min(Low[u], Low[v]);
        } else if(inStack[v]) {
            Low[u] = min(Low[u], Low[v]);
        }
    }
    if(DFN[u] == Low[u]) {
        bsz++; int v;
        do {
            v = Stack[ssz--];
            inStack[v] = 0;
            Belong[v] = bsz;
        } while(ssz && v != u);
    }
}
void tarjan_solve(int n) {
    dsz = bsz = ssz = 0;
    memset(DFN, 0, sizeof(DFN));
    for(int i = 1; i <= n; i++) {
        if(!DFN[i]) trajan(i, -1);
    }
    /*缩点*/
    edge_init();
    for(int i = 0; i < 2 * m; i += 2) {
        int u = E[i].u, v = E[i].v;
        u = Belong[u]; v = Belong[v];
        if(u == v) continue;
        edge_add(u, v);
        edge_add(v, u);
    }
}

int main() {
    //FIN
    int m, n;
    while(~scanf("%d%d", &m, &n)) {
        edge_init();
        for(int i = 1; i <= n; i++) {
            int u, v;
            scanf("%d%d", &u, &v);
            edge_add(u, v);
            edge_add(v, u);
        }
        tarjan_solve(n);
        int Q;
        scanf("%d", &Q);
        for(int i = 1; i <= Q; i++) {
            int u, v;
            scanf("%d%d", &u, &v);
            if(Belong[u] == Belong[v]) printf("Yes\n");
            else printf("No\n");
        }

    }
    return 0;
}

  

				
时间: 2024-10-20 06:00:39

51nod 1076 2条不相交的路径 无向图强联通分量 trajan算法的相关文章

51nod 1076 2条不相交的路径(边双连通分量)

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1076 题意: 思路: 边双连通分量,跑一遍存储一下即可. 1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<sstream> 6 #include<vector> 7 #in

51nod 1076 2条不相交的路径

思路:强连通,将他变成有向图,并且不能返回父节点 1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=30000; 4 5 struct node{ 6 int v,next; 7 }edg[50004*3]; 8 int head[maxn],tot=0; 9 void add(int u,int v){ 10 edg[tot].v=v;edg[tot].next=head[u];head[u]=tot++; 1

无向图的联通分量

无向图的联通分量环啊,桥啊,生成树的边啊,联通分量啊,就是一个东西 Unique Path https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4055 这个题是把环去掉,其他的树上有n个点,就有n*(n-1)/2 对. 1 #include<cstdio> 2 #include<cstring> 3 #i

HDU 3861.The King’s Problem 强联通分量+最小路径覆盖

The King’s Problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 2947    Accepted Submission(s): 1049 Problem Description In the Kingdom of Silence, the king has a new problem. There are N cit

hihoCoder#1185 : 连通性&#183;三 tarjan求强联通分量 缩点 dfs/拓扑排序求路径和最大值

题目链接: http://hihocoder.com/problemset/problem/1185# 题意: n个点,每个点有一个权值,m条有向边,从1出发,每走到一个点, 就吃掉这个点的草,当没有可以到达的草场或是能够到达的草场都已经被吃光了之后就要返回到1了.求最多可以吃掉多少草. 思路: 提示里面讲的挺好的 如果草场是一个强连通图,那么我们只要走到任意一点,就可以把其他所有的草场都走一遍,并且可以选择任意一个点作为终点.所以把强联通块缩成一个点 因为一个强连通块会被缩成一个点,那么我们可

POJ 1236--Network of Schools【scc缩点构图 &amp;&amp; 求scc入度为0的个数 &amp;&amp; 求最少加几条边使图变成强联通】

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

无向图的强连通分量

在学习无向图的强联通分量之前 你首先要明白有向图的强联通分量 定义 对于任意两个点,如果存在至少两条互相不重合的路径,使得这两点可以相互到达,那么这两个点就属于同一个强联通分量 比如说 在这张图中, $1,2,3$属于一个强联通分量 $4$属于一个强联通分量,因为$3,4$只有一条可以相互到达的路径 实现 和有向图的强联通分量类似 都是用Tarjan算法实现 在求无向图的强联通分量重,我们不允许走已经走过的边 所以我们在Tarjan的过程中还需要记录一个father 走的时候只能走目标节点不是f

无向图的双联通分量

点双和边双的区别我在上一篇文章中已经讨论过了,这篇文章讲边双的求法. 由于是边双,就决定了边双中一定不含有桥,但是可以含有割顶. 所以我们对边双唯一的限制条件就是不经过桥. 如此一来,我们可以分成两次dfs,第一次求出所有的桥,第二次dfs时遍历整张图,只要保证不经过桥就可以了. #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <s

给出一张DAG图,问最少加多少条有向边s.t.其强联通?

对于这个问题,可以简化成以下等价(证明略去)版本: 给出一张n个点的DAG图,图中的点出度(简称cd)或者入度(简称rd)为0,问最少加多少有向条边,s.t.其强联通? 定理1:对于一张n个点的DAG图,图中的点出度或者入度为0,最少只需要加n-1条有向边,就可以使其强联通. ·证明:初始状态下,加入第一条边,至多产生一个强联通分量,并且这个强联通分量中只包含两个点(证明略去).为了最小化加入有向边的数目,之后加入的有向边,一定不在这个强联通分量内部(因为它不会使得强联通分量的大小增加).而无论