NC51307 Redundant Paths
题目:
• 给定无向连通图,求至少需要添加几条边使它变成一个边双连通图。
(添多少边可以消灭所有的桥)
题解:
先用边双连通缩点
• 缩点之后是一棵树
• 无根树的叶子(度数为1的点)都需要再添一条边,叶子节点两两连接
• 答案是是(叶子数+1)/2

代码:
这个题最坑的地方在于存在重边,我一直被卡。。。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<stack>
typedef long long ll;
using namespace std;
inline int read(){
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();//s=(s<<3)+(s<<1)+(ch^48);
return s*w;
}
int n,m;
const int maxn=1e4+9;
vector<int>edge[maxn];
int low[maxn],dfn[maxn],vis[maxn];
int cnt=0;
int color[maxn],block=0;
stack<int>s;
int out[maxn];
int iff[maxn][maxn];
void tarjan(int u,int fa)
{
low[u]=dfn[u]=++cnt;
vis[u]=1;
s.push(u);
int b=0;
for(int i=0;i<edge[u].size();i++)
{
int v=edge[u][i];
if(v==fa&&!b){b=1;continue;}
if(!dfn[v])
{
tarjan(v,u);
low[u]=min(low[u],low[v]);
}
else low[u]=min(low[u],dfn[v]);
}
int x;
if(dfn[u]==low[u])
{
block++;
do
{
x=s.top();
s.pop();
vis[x]=0;
color[x]=block;
}while(x!=u);
}
}
int lu[maxn],lv[maxn];
int main()
{
// freopen("P2860_9.in","r",stdin);
cin>>n>>m;
for(int i=1;i<=m;i++)
{
int u,v;
cin>>u>>v;
lu[i]=u;
lv[i]=v;
edge[u].push_back(v);
edge[v].push_back(u);
}
for(int i=1;i<=n;i++)
{
if(!dfn[i])tarjan(i,0);
}
int ans=0;
for(int i=1;i<=m;i++)
{
int u=lu[i];
int v=lv[i];
int x=color[u];
int y=color[v];
if(x!=y)
{
out[y]++;
out[x]++;
}
}
for(int i=1;i<=block;i++)
{
if(out[i]==1)ans++;
}
//ans++;
cout<<(ans+1)/2;
}

京公网安备 11010502036488号