HDU 4612 边双连通+缩点
2 处理重边问题
问题:
无向图将边双联通分量缩点后添加一条边使得割边数量变得最少,最少是多少?
思路:
在2个距离最远的点添加一条边使得割边消失的最多,那么剩下的割边最少
先
dfs
一次找到距离最远的2个点中的1个.(同时记录缩点后割边的总数),再一次
dfs
就能统计到另一个最远点的路径上的割边数量.技巧
for (int j=head[i]; j!=-1; j=edge[j].next)
遍历每个点的邻接表来建立缩点后无向图(vector
存)e[i].vis
来处理重边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#include <iostream>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 2e5+10;
struct node {
int to,next;
bool vis;
} edge[maxn*10];
vector<int> e[maxn];
int head[maxn],h[maxn],index1;
int low[maxn],dfn[maxn],belong[maxn],stack_[maxn];
int top,dps,cir,n,m;
bool in_stack[maxn];
void tarjan(int x) {
in_stack[x] = 1;
low[x] = dfn[x] = ++dps;
stack_[top++] = x;
for (int i=head[x]; i+1; i=edge[i].next) {
int to = edge[i].to;
if (edge[i].vis) continue;
edge[i].vis = edge[i^1].vis = 1;
if (!dfn[to]) {
tarjan(to);
low[x] = min(low[x],low[to]);
} else if (in_stack[to])
low[x] = min(low[x],dfn[to]);
}
int p;
if (low[x] == dfn[x]) {
cir++;
do{
p = stack_[--top];
in_stack[p] = 0;
belong[p] = cir;
}while(p != x);
}
}
bool vis[maxn];
int point,max_edge,ans;
void dfs(int x,int step) {
vis[x] = 1;
if (step > max_edge) max_edge=step,point = x;
for (int i=0; i<e[x].size(); ++i) {
int to = e[x][i];
if (!vis[to]) {
dfs(to,step+1);
ans++;
}
}
}
void add(int x,int y) {
edge[index1].vis = 0;
edge[index1].to = y;
edge[index1].next = head[x];
head[x] = index1++;
}
void init() {
index1 = 0;
memset(head,-1,sizeof head);
memset(in_stack,0,sizeof in_stack);
memset(low,0,sizeof low);
memset(dfn,0,sizeof dfn);
dps = top = cir = 0;
}
int main() {
freopen("1.in","r",stdin);
while (scanf("%d%d",&n,&m) && (n+m)) {
init();
for (int i=1; i<=m; ++i) {
int x,y;
scanf("%d%d",&x,&y);
add(x,y); add(y,x);
}
tarjan(1);
for (int i=1; i<=n; ++i) e[i].clear();
for (int i=1; i<=n; ++i)
for (int j=head[i]; j!=-1; j=edge[j].next) {
int to = edge[j].to;
if (belong[to] != belong[i]) {
e[belong[i]].push_back(belong[to]);
}
}
memset(vis,0,sizeof vis);
max_edge = ans = 0;
dfs(1,0);
int tempans = ans;
memset(vis,0,sizeof vis);
max_edge = 0;
dfs(point,0);
cout << tempans-max_edge << endl;
}
return 0;
}
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!