题目大意:有一个人奇怪的人想要铺路,这个人想把每个环都铺上石头,但是铺石头时不能重复铺,如果重复铺的话,这条边就算损坏
问这个人要损坏多少条边,有多少条边可以不用铺石头
解题思路:不用铺石头的边肯定是桥,因为桥不属于任意一个环
接着判断一下有多少条边会冲突,首先,一个环的话肯定是点-双连通,但点-双连通不一定是个环,所以这个要判断一下。
一个正常的环是要满足 边数=点数 的,如果边数比点数多了,证明这个环被分割成至少三个环了(一个最外围的环,两个被分的小环),可以看出,这三个环每条边都冲突
所以只要满足边数>点数的,都可以证明这个环的所有边冲突
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
#define N 10010
#define M 200010
#define min(a,b) ((a) < (b) ? (a): (b))
struct Edge{
int from, to, next, id;
Edge() {}
Edge(int from, int to) :from(from), to(to){}
}E[M];
int n, m, tot, dfs_clock, bnum, bcc_cnt, top;
int head[N], pre[N], stack[M], low[N], num[N];
vector<int> edge[N];
bool vis[N];
void AddEdge(int u, int v) {
E[tot].from = u; E[tot].to = v; E[tot].next = head[u]; E[tot].id = tot; head[u] = tot++;
u = u ^ v; v = u ^ v; u = v ^ u;
E[tot].from = u; E[tot].to = v; E[tot].next = head[u]; E[tot].id = tot; head[u] = tot++;
}
void init() {
memset(head, -1, sizeof(head));
tot = 0;
int u, v;
for (int i = 0; i < m; i++) {
scanf("%d%d", &u, &v);
AddEdge(u, v);
}
}
void dfs(int u, int fa) {
pre[u] = low[u] = ++dfs_clock;
for (int i = head[u]; i != -1; i = E[i].next) {
int v = E[i].to;
if (!pre[v]) {
stack[++top] = E[i].id;
dfs(v, u);
low[u] = min(low[u], low[v]);
if (low[v] >= pre[u]) {
bcc_cnt++;
edge[bcc_cnt].clear();
int x, id;
while (1) {
id = stack[top--];
edge[bcc_cnt].push_back(id);
x = E[id].from;
if (x == u)
break;
}
if (low[v] > pre[u])
bnum++;
}
}
else if(pre[v] < pre[u] && v != fa) {
low[u] = min(low[u], pre[v]);
stack[++top] = E[i].id;
}
}
}
void solve() {
memset(pre, 0, sizeof(pre));
dfs_clock = bcc_cnt = bnum = top = 0;
for (int i = 0; i < n; i++)
if (!pre[i])
dfs(i, -1);
int ans = 0;
for (int i = 1; i <= bcc_cnt; i++) {
for (int j = 0; j < n; j++)
vis[j] = false;
int size = edge[i].size(), cnt = 0;
for (int j = 0; j < size; j++) {
if (!vis[E[edge[i][j]].from]) {
vis[E[edge[i][j]].from] = true;
cnt++;
}
if (!vis[E[edge[i][j]].to]) {
vis[E[edge[i][j]].to] = true;
cnt++;
}
}
if (size > cnt)
ans += size;
}
printf("%d %d\n", bnum, ans);
}
int main() {
while (scanf("%d%d", &n, &m) != EOF && n + m) {
init();
solve();
}
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-10-25 10:58:45