【POJ 3177】Redundant Paths(边双连通分量)

时间:2021-10-03 08:52:15

求出每个边双连通分量缩点后的度,度为1的点即叶子节点。原图加上(leaf+1)/2条边即可变成双连通图。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <map> using namespace std;
const int N = ;
const int M = ;
struct Edge
{
int to,next;
bool cut;
}edge[M];
int head[N],tot;
int Low[N],DFN[N],Stack[N],Belong[N];
int Index,top;
int block;
bool Instack[N];
int bridge;
void addedge(int u,int v)
{
edge[tot].to = v;edge[tot].next = head[u];head[u] = tot++;
edge[tot].cut=false;
}
void Tarjan(int u,int pre)
{
int v;
Low[u] = DFN[u] = ++Index;
Stack[top++] = u;
Instack[u] = true;
for(int i = head[u];~i;i = edge[i].next)
{
v = edge[i].to;
if(v == pre)continue;
if( !DFN[v] )
{
Tarjan(v,u);
if( Low[u] > Low[v] )Low[u] = Low[v];
if(Low[v] > DFN[u])//桥
{
bridge++;
edge[i].cut = true;
edge[i^].cut = true;
}
}
else if(Instack[v] && Low[u] > DFN[v])
Low[u] = DFN[v];
}
if(Low[u] == DFN[u])
{
block++;
do
{
v = Stack[--top];
Instack[v] = false;
Belong[v] = block;
}
while( v != u);
}
}
int du[N];//缩点后形成树,每个点的度数
void solve(int n)
{
memset(DFN,,sizeof(DFN));
memset(Instack,false,sizeof Instack);
Index = block = top = ;
Tarjan(,);
int ans = ;
memset(du,,sizeof(du));
for(int i = ;i <= n;i++)
for(int j = head[i];~j;j = edge[j].next)
if(edge[j].cut)
du[Belong[i]]++;
for(int i = ;i <= block;i++)
if(du[i]==)
ans++;
printf("%d\n",(ans+)/);
}
void init()
{
tot = ;
memset(head,-,sizeof head);
}
int main()
{
int n,m;
int u,v;
while(scanf("%d%d",&n,&m)==)
{
init();
while(m--)
{
scanf("%d%d",&u,&v);
addedge(u,v);
addedge(v,u);
}
solve(n);
}
return ;
}