题目来源:Light OJ 1291 Real Life Traffic
题意:最少添加几条边 可以使全图边双连通
思路:缩点 重新构图 答案就是(叶子节点数+1)/ 2
#include <vector>
#include <cstdio>
#include <cstring>
#include <stack>
#include <algorithm>
using namespace std;
const int maxn = 10010;
struct Edge
{int u, v;Edge(){}Edge(int u, int v): u(u), v(v){}
};
vector <int> a[maxn];
int pre[maxn];
int low[maxn];
int bccno[maxn];
int dfs_clock;
int bcc_cnt;
int bri;
int n, m;
int degree[maxn];
stack <int> S;void dfs(int u, int fa)
{low[u] = pre[u] = ++dfs_clock;S.push(u);for(int i = 0; i < a[u].size(); i++){int v = a[u][i];if(v == fa)continue;if(!pre[v]){dfs(v, u);low[u] = min(low[u], low[v]);}else if(v != fa)low[u] = min(low[u], pre[v]);}if(low[u] == pre[u]){bcc_cnt++;while(1){int x = S.top(); S.pop();bccno[x] = bcc_cnt;if(x == u)break;}}
}
void find_bcc()
{memset(pre, 0, sizeof(pre));memset(bccno, 0, sizeof(bccno));dfs_clock = bcc_cnt = bri = 0;for(int i = 0; i < n; i++)if(!pre[i])dfs(i, -1);
}
int main()
{int cas = 1;int T;scanf("%d", &T);while(T--){scanf("%d %d", &n, &m);for(int i = 0; i <= n; i++)a[i].clear();while(m--){int u, v;scanf("%d %d", &u, &v);a[u].push_back(v);a[v].push_back(u);}find_bcc();memset(degree, 0, sizeof(degree));for(int u = 0; u < n; u++){for(int i = 0; i < a[u].size(); i++){int v = a[u][i];if(bccno[u] != bccno[v]){degree[bccno[u]]++;degree[bccno[v]]++;}}}int ans = 0;for(int i = 1; i <= bcc_cnt; i++)if(degree[i] == 2)ans++;printf("Case %d: %dn", cas++, (ans+1)/2);}return 0;
}
本文发布于:2024-02-05 03:52:00,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170723405962820.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |