「BZOJ-1718」「POJ-3177」Redundant Paths

为了从F($1 \leq F \leq 5000$)个草场中的一个走到另一个,贝茜和她的同伴们有时不得不路过一些她们讨厌的可怕的树.奶牛们已经厌倦了被迫走某一条路,所以她们想建一些新路,使每一对草场之间都会至少有两条相互分离的路径,这样她们就有多一些选择.

每对草场之间已经有至少一条路径.给出所有R($F-1 \leq R \leq 10000$)条双向路的描述,每条路连接了两个不同的草场,请计算最少的新建道路的数量, 路径由若干道路首尾相连而成.两条路径相互分离,是指两条路径没有一条重合的道路.但是,两条分离的路径上可以有一些相同的草场. 对于同一对草场之间,可能已经有两条不同的道路,你也可以在它们之间再建一条道路,作为另一条不同的道路.

链接

BZOJ-1718

POJ-3177

题解

先缩点,之后形成一棵树,也就是求出双连通分量,然后求 (叶子节点数量 + 1) / 2即可。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#include <bits/stdc++.h>
#define FAST_IO
#ifdef FAST_IO
const int IN_LEN = 1000, OUT_LEN = 1000;
inline int nextChar() {
static char buf[IN_LEN], *h, *t;
if (h == t) {
t = (h = buf) + fread(buf, 1, IN_LEN, stdin);
if (h == t) return -1;
}
return *h++;
}
template<class T>
inline bool read(T &x) {
static bool iosig = 0;
static char c;
for (iosig = 0, c = nextChar(); !isdigit(c); c = nextChar()) {
if (c == -1) return false;
if (c == '-') iosig = 1;
}
for (x = 0; isdigit(c); c = nextChar()) x = (x << 1) + (x << 3) + (c ^ '0');
if (iosig) x = -x;
return true;
}
char obuf[OUT_LEN], *oh = obuf;
inline void writeChar(const char c) {
if (oh == obuf + OUT_LEN) fwrite(obuf, 1, OUT_LEN, stdout), oh = obuf;
*oh++ = c;
}
template<class T>
inline void write(T x) {
static int buf[30], cnt;
if (!x) writeChar(48);
else {
if (x < 0) writeChar('-'), x = -x;
for (cnt = 0; x; x /= 10) buf[++cnt] = x % 10 + 48;
while (cnt) writeChar(buf[cnt--]);
}
}
inline void flush() { fwrite(obuf, 1, oh - obuf, stdout); }
#endif
const int MAXN = 5005;
std::vector<int> edge[MAXN];
std::stack<int> st;
int dfn[MAXN], low[MAXN], idx, id[MAXN], scc;
inline void init() {
while (!st.empty()) st.pop();
idx = 0, scc = 1;
memset(id, -1, sizeof(id));
memset(edge, 0, sizeof(edge));
memset(dfn, -1, sizeof(dfn));
memset(low, -1, sizeof(low));
}
inline void addEdge(const int u, const int v) {
edge[u].push_back(v);
edge[v].push_back(u);
}
inline void tarjan(int u, int fa) {
dfn[u] = low[u] = ++idx, st.push(u);
bool flag = 0;
for (register int i = 0; i < edge[u].size(); i++) {
register int v = edge[u][i];
if (v == fa && !flag) {
flag = 1;
continue;
}
if (dfn[v] == -1) tarjan(v, u), low[u] = std::min(low[u], low[v]);
else low[u] = std::min(low[u], dfn[v]);
}
if (low[u] == dfn[u]) {
register int v;
do v = st.top(), id[v] = scc, st.pop(); while (!st.empty() && v != u);
scc++;
}
}
inline void solve(const int n, int &ans) {
register int u, v;
static int deg[MAXN];
memset(deg, 0, sizeof(deg));
for (register int i = 1; i <= n; i++) {
for (register int j = 0; j < edge[i].size(); j++) {
u = i, v = edge[i][j];
if (id[u] == id[v]) continue;
else deg[id[v]]++, deg[id[u]]++;
}
}
register int sum = 0;
for (register int i = 1; i < scc; i++)
if (deg[i] == 2)
sum++;
ans = sum + 1 >> 1;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("in.in", "r", stdin);
#endif
register int n, m;
while (read(n), read(m)) {
init();
register int u, v;
for (register int i = 0; i < m; i++) read(u), read(v), addEdge(u, v);
tarjan(1, 1);
register int ans;
solve(n, ans);
write(ans), writeChar('\n');
}
flush();
return 0;
}

Comments

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×