51nod 1241 特殊的排序 (双连通分量)

简介: 51nod 1241 特殊的排序 (双连通分量)

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

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

输入

第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,中间用空格分隔,表示查询的起点和终点。

输出

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

输入样例

4 4

1 2

2 3

1 3

1 4

5

1 2

2 3

3 1

2 4

1 4

输出样例

Yes

Yes

Yes

No

No


仔细分析一下应该就可以看出来如果两个点之间有两条不想交的路径,那么肯定两个点在一个联通分支上,并且这两个点在环上,所以其实就是去掉桥之后的两个点是否属于一个联通分支。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
int head[maxn], tot;
int u[maxn], v[maxn];
int vis[maxn], low[maxn], dfn[maxn];
struct Edge {
  int u, v, next, id;
}edge[maxn];
int n, m, Index;
int col[maxn];
void  init() {
  memset(head, -1, sizeof(head));
  tot = 1;
}
void add(int u, int v, int id) {
  edge[++tot].u = u; edge[tot].v = v;
  edge[tot].id = id;
  edge[tot].next = head[u];
  head[u] = tot;
}
void tarjan(int u, int fa) {
  low[u] = dfn[u] = ++Index;
  for (int i = head[u]; i != -1; i = edge[i].next) {
    int to = edge[i].v;
    if (to == fa) {
      continue;
    }
    if (!dfn[to]) {
      tarjan(to, u);
      low[u] = min(low[u], low[to]);
      if (low[to] > dfn[u]) {
        vis[edge[i].id] = 1;  
      }
    } else {
      low[u] = min(low[u], dfn[to]);
    }
  }
}
void dfs(int u, int c) {
  col[u] = c;
  for (int i = head[u]; i != -1; i = edge[i].next) {
    int to = edge[i].v;
    if (!col[to]) {
      dfs(to, c);
    }
  }
}
int main() {
  ios::sync_with_stdio(false);
  cin.tie(0); cout.tie(0);
  init();
  cin >> n >> m;
  for (int i = 1; i <= m; i++) {
    cin >> u[i] >> v[i];
    add(u[i], v[i], i); add(v[i], u[i], i);
  }
  for (int i = 1; i <= n; i++) {
    if (!dfn[i]) {
      tarjan(i, i);
    }
  }
  init();
  for (int i = 1; i <= m; i++) {
    if (!vis[i]) {
      add(u[i], v[i], i);
      add(v[i], u[i], i);
    }
  }
  for (int i = 1; i <= n; i++) {
    if (!col[i]) {
      dfs(i, i);
    }
  }
  int q, x, y;
  cin >> q;
  while (q--) {
    cin >> x >> y;
    if (col[x] != col[y]) {
      cout << "No" << endl;
    } else {
      cout << "Yes" << endl;
    }
  }
  return 0;
} 
相关文章
|
9月前
BM12单链表的排序
BM12单链表的排序
28 0
|
机器学习/深度学习 Windows
51nod 1258序列求和
51nod 1258序列求和
62 0
51nod 1292 字符串中的最大值 V2 (后缀数组)
51nod 1292 字符串中的最大值 V2 (后缀数组)
46 0
|
人工智能
51nod 1624 取余最长路 (set 二分)
51nod 1624 取余最长路 (set 二分)
60 0
|
人工智能 vr&ar
SPOJ - COT Count on a tree(主席树 LCA)
SPOJ - COT Count on a tree(主席树 LCA)
80 0