E - Redundant Paths
题目大意:给一个连通图,求至少加上几条边才能使原图的任意两点之间至少有两条边不重复的路径。
解题思路:因为题目要求边不重复的路径,因此应该考虑边双联通分量,无向图边连通分量缩点之后是一树
我们将左子树右子树的叶子节点连通即可。最终答案就是(叶子节点+1)/2;
写起来细节还挺多。
对于一个连通图我们可以通过一次dfs找出所有的桥,然后再一次dfs找出所有的边双联通分量。然后就是统计度数
因为是双向边,所以度数要/2;
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<stack>
#include<map>
#include<algorithm>
using namespace std;
#define LL long long
#define sca(x) scanf("%d",&x)
#define lowb(x) (x&(-x))
#define pb(x) push_back(x)
#define rep(i,j,k) for(int i=j;i<=k;i++)
#define per(i,j,k) for(int i=j;i>=k;i--)
#define pri(x) printf("%d\n",x);
#define N 100005
#define inf 0x3f3f3f3f
const LL mod=1e9+7;
struct node
{
int to,nt,id;
}g[N];
int head[N];
int tot;
void addedg(int x,int y,int id)
{
g[tot].to=y;
g[tot].id=id;
g[tot].nt=head[x];
head[x]=tot++;
}
int low[N],df[N];
int bel[N],vis[N];
int du[N];
int clo,cnt;
void dfs(int now,int fa)
{
df[now]=low[now]=++clo;
for(int i=head[now];i+1;i=g[i].nt)
{
int to=g[i].to;
if(!df[to])
{
dfs(to,now);
low[now]=min(low[now],low[to]);
if(low[to]>df[now])
{
vis[g[i].id]=1;
}
}
else if(df[to]<df[now]&&to!=fa)
{
low[now]=min(low[now],df[to]);
}
}
}
void dfs1(int u)
{
bel[u]=cnt;
for(int i=head[u];i+1;i=g[i].nt)
{
if(!vis[g[i].id]&&!bel[g[i].to])
{
dfs1(g[i].to);
}
}
}
void solve(int n)
{
dfs(1,-1);
cnt=1;
rep(i,1,n)if(!bel[i])dfs1(i),cnt++;
rep(i,1,n)
{
for(int j=head[i];j+1;j=g[j].nt)
{
if(bel[i]!=bel[g[j].to])du[bel[i]]++,du[bel[g[j].to]]++;
}
}
int ans=0;
rep(i,1,cnt-1)if(du[i]==2)ans++;
cout<<(ans+1)/2<<endl;
}
int main()
{
int n,m;
memset(head,-1,sizeof(head));
scanf("%d%d",&n,&m);
rep(i,1,m)
{
int x,y;
scanf("%d%d",&x,&y);
addedg(x,y,i);
addedg(y,x,i);
}
solve(n);
}