POJ 3713 割点

链接:

http://poj.org/problem?id=3713

题意:

给出一个无向图(可能不联通),判断是否每两个点之间都能至少有3条独立不同的路径可达。独立定义为任意两条路径只有起点和

终点相同,其他点均不相同。

思路:

图的三联通判断。枚举删去一个点看是否存在割点,如果存在那么说明不满足。

代码:

 

 1 #include <map>
 2 #include <set>
 3 #include <cmath>
 4 #include <queue>
 5 #include <stack>
 6 #include <cstdio>
 7 #include <string>
 8 #include <vector>
 9 #include <cstdlib>
10 #include <cstring>
11 #include <sstream>
12 #include <iostream>
13 #include <algorithm>
14 #include <functional>
15 using namespace std;
16 #define rep(i,a,n) for (int i=a;i<n;i++)
17 #define per(i,a,n) for (int i=n-1;i>=a;i--)
18 #define all(x) (x).begin(),(x).end()
19 #define pb push_back
20 #define mp make_pair
21 #define lson l,m,rt<<1  
22 #define rson m+1,r,rt<<1|1 
23 typedef long long ll;
24 typedef vector<int> VI;
25 typedef pair<int, int> PII;
26 const ll MOD = 1e9 + 7;
27 const int INF = 0x3f3f3f3f;
28 const int MAXN = 2e4 + 7;
29 // head
30 
31 int n, m, order = 0;
32 int low[MAXN], dfn[MAXN];
33 int par[MAXN], son[MAXN];
34 int vis[MAXN];
35 VI G[MAXN];
36 VI cutpoint;
37 vector<PII> cutedge;
38 int fg;
39 
40 void tarjan(int u) {
41     if (fg) return;
42     vis[u] = 1;
43     dfn[u] = low[u] = ++order;
44     bool flag = false;
45     rep(i, 0, G[u].size()) {
46         int v = G[u][i];
47         if (vis[v] == 2) continue;
48         if (!dfn[v]) {
49             son[u]++;
50             par[v] = u;
51             tarjan(v);
52             if (low[v] >= dfn[u]) flag = true;
53             low[u] = min(low[u], low[v]);
54         }
55         else if (v != par[u]) low[u] = min(low[u], dfn[v]);
56     }
57     if ((par[u] == -1 && son[u] > 1) || (par[u] != -1 && flag)) fg = 1;
58 }
59 
60 void init() {
61     order = 0;
62     memset(low, 0, sizeof(low));
63     memset(dfn, 0, sizeof(dfn));
64     memset(par, 0, sizeof(par));
65     memset(son, 0, sizeof(son));
66     memset(vis, 0, sizeof(vis));
67 }
68 
69 int main()
70 {
71     while (cin >> n >> m, n) {
72         rep(i, 0, MAXN) G[i].clear();
73         while (m--) {
74             int a, b;
75             scanf("%d%d", &a, &b);
76             G[a].pb(b);
77             G[b].pb(a);
78         }
79         fg = 0;
80         rep(k, 0, n) {
81             init();
82             vis[k] = 2;
83             int root = k ? 0 : 1;
84             par[root] = -1;
85             tarjan(root);
86             rep(i, 0, n) if (!vis[i]) {
87                 fg = 1;
88                 break;
89             }
90             if (fg) break;
91         }
92         if (fg) cout << "NO" << endl;
93         else cout << "YES" << endl;
94     }
95     return 0;
96 }

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值