POJ 3352
题目链接:
http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=11219
题意:
一些点之间有边相连,保证整个图连通。问至少增加几条边,能使得去掉任意一条原始边后原图仍然保持连通。
思路:
双连通缩点版题。
最后答案为(缩点树种度为1的点个数+1)/2。因为是测版,所以看题解过的~
源码:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <iostream>
#include <utility>
#include <vector>
using namespace std;
#define gmax(a,b) ((a) > (b) ? (a) : (b))
#define gmin(a,b) ((a) < (b) ? (a) : (b))
const int MAXN = 1000 + 5;
typedef pair<int, int>pii;
vector<pii>lin[MAXN];
int n, m;
int bridge[MAXN];
int U[MAXN], V[MAXN];
int low[MAXN], pre[MAXN], clock;
int NewId[MAXN], IDs; ///新点标号,总的新点数
int vis[MAXN];
void edge_init()
{
for(int i = 1 ; i <= n ; i++)
lin[i].clear();
int u, v;
for(int i = 1 ; i <= m ; i++){
scanf("%d%d", &u, &v);
lin[u].push_back(make_pair(v, i));
lin[v].push_back(make_pair(u, i));
U[i] = u, V[i] = v;
}
}
void DFS_bridge(int u, int fa)
{
pre[u] = low[u] = ++clock;
for(int i = 0 ; i < (int)lin[u].size() ; i++){
pii temp = lin[u][i];
int v = temp.first, ID = temp.second;
if(pre[v] == 0){
DFS_bridge(v, u);
low[u] = gmin(low[u], low[v]);
if(low[v] > pre[u]) bridge[ID] = 1;
}
else if(pre[v] != 0 && v != fa)
low[u] = gmin(low[u], pre[v]);
}
}
void DFS_shrink(int u, int fa)
{
NewId[u] = IDs;
vis[u] = 1;
for(int i = 0 ; i < (int)lin[u].size() ; i++){
int v = lin[u][i].first;
int ID = lin[u][i].second;
if(!bridge[ID] && v != fa && vis[v] == 0){
DFS_shrink(v, u);
}
}
}
void BCC_bridge()
{
memset(bridge, 0, sizeof(bridge));
memset(pre, 0, sizeof(pre));
clock = 0;
for(int i = 1 ; i <= n ; i++)
if(pre[i] == 0)
DFS_bridge(1, -1);
}
void Shrink() ///关键函数
{
memset(vis, 0, sizeof(vis));
IDs = 0;
for(int i = 1 ; i <= n ; i++){
if(vis[i] == 0){
++IDs;
DFS_shrink(i, -1);
}
}
for(int i = 1 ; i <= n ; i++)
lin[i].clear();
for(int i = 1 ; i <= m ; i++){ ///新点的边
if(bridge[i]){
int u = NewId[U[i]], v = NewId[V[i]];
lin[u].push_back(make_pair(v, i));
lin[v].push_back(make_pair(u, i));
}
}
}
int main()
{
while(scanf("%d%d", &n, &m) != EOF){
edge_init();
BCC_bridge();
Shrink();
int ans = 0;
for(int i = 1; i <= IDs ; i++){
if(lin[i].size() == 1){
// printf("i = %d\n", i);
ans++;
}
}
ans = (ans + 1) / 2;
printf("%d\n", ans);
}
return 0;
}
/*
7 6
1 2
2 3
3 4
4 5
5 6
1 7
*/