题意:给你一个图,问至少需要加多少条路使得整个图成为边双连通。
求出割边并缩点,可以得到一棵树,统计树上所有度为1的点数,最后的答案就是(cnt+1)/2,这个画个图就明白了。
ps:这题坑了我两个wa,输入和输出原来不需要Sample Input 1。。太坑了
#include <stdio.h>
#include <string.h>
const int maxn = 1002;
const int maxm = 1005;
struct EDGE{
int to, next, vis;
}edge[maxm<<1];
int head[maxn], dfn[maxn], belo[maxn], low[maxn], st[maxn];
int E, time, top, gtot, type;
struct GEDGE{
int u, to;
}gedge[maxm];
void newedge(int u, int to) {
edge[E].to = to;
edge[E].next = head[u];
edge[E].vis = 0;
head[u] = E++;
}
void init() {
memset(head, -1, sizeof(head));
memset(dfn, 0, sizeof(dfn));
memset(belo, 0, sizeof(belo));
E = time = type = top = gtot = 0;
}
int min(int a, int b) {
return a > b ? b : a;
}
void dfs(int u) {
dfn[u] = low[u] = ++time;
st[++top] = u;
for(int i = head[u];i != -1;i = edge[i].next) {
if(edge[i].vis) continue;
edge[i].vis = edge[i^1].vis = 1;
int to = edge[i].to;
if(!dfn[to]) {
dfs(to);
low[u] = min(low[u], low[to]);
if(low[to] > dfn[u]) {
type++;
int v;
do {
v = st[top--];
belo[v] = type;
} while(v != to);
gedge[gtot].u = u;
gedge[gtot++].to = to;
}
}
else
low[u] = min(low[u], low[to]);
}
}
int ans ;
void DFS(int u, int pre) {
int tot = 0;
if(pre != -1) tot++;
for(int i = head[u];i != -1;i = edge[i].next) {
int to = edge[i].to;
if(to != pre) {
DFS(to, u);
tot++;
}
}
if(tot == 1) ans++;
}
char s[111];
int main() {
int n, m, i, u, to;
while(scanf("%d%d", &n, &m) != -1) {
init();
for(i = 0;i < m;i ++) {
scanf("%d%d", &u, &to);
newedge(u, to);
newedge(to, u);
}
for(i = 1;i <= n; i++) if(!dfn[i])
dfs(i);
memset(head, -1, sizeof(head));
E = 0;
for(i = 0;i < gtot; i++) {
u = belo[gedge[i].u];
to = belo[gedge[i].to];
newedge(u, to);
newedge(to, u);
}
ans = 0;
DFS(0, -1);
printf("%d\n", (ans+1)/2);
}
return 0;
}