POJ3352Road Construction(无向图强连通)

http://poj.org/problem?id=3352

无向图强连通分量缩点 知道一个等式:

若要使得任意一棵树,在增加若干条边后,变成一个双连通图,那么

至少增加的边数 =( 这棵树总度数为1的结点数 + 1 )/ 2

 #include <iostream>
#include<cstdio>
#include<cstring>
#include<stack>
#include<algorithm>
#include<stdlib.h>
using namespace std;
#define N 1010
#define M 2010
struct node
{
int u,v,next;
}edge[M];
stack<int>s;
int head[N],pre[N],low[N],sccno[N],scc,dep,t,de[N],vis[N],w[N][N];
void init()
{
t = ;
memset(head,-,sizeof(head));
scc=;dep=;
memset(sccno,,sizeof(sccno));
memset(low,,sizeof(low));
memset(pre,,sizeof(pre));
memset(vis,,sizeof(vis));
}
void add(int u,int v)
{
edge[t].u = u;
edge[t].v = v;
edge[t].next = head[u];
head[u] = t++;
}
void dfs(int u,int fa)
{
low[u] = pre[u] = ++dep;
s.push(u);
for(int i = head[u] ; i!=- ; i = edge[i].next)
{
int v = edge[i].v;
if(v==fa) continue;
if(!pre[v])
{
dfs(v,u);
low[u] = min(low[u],low[v]);
}
else if(!sccno[v])
low[u] = min(low[u],pre[v]);
}
if(low[u]==pre[u])
{
scc++;
for(;;)
{
int x = s.top();s.pop();
sccno[x] = scc;
if(x==u) break;
}
}
}
int main()
{
int i,n,m,kk=;
char str[];
while(cin>>n>>m)
{
kk++;init();
memset(w,,sizeof(w));
memset(de,,sizeof(de));
int a,b;
while(m--)
{
scanf("%d%d",&a,&b);
add(a,b);add(b,a);
}
dfs(,);
for(i = ; i < t ; i++)
{
int u = edge[i].u,v = edge[i].v;
if(!w[u][v]&&sccno[u]!=sccno[v])
{
w[u][v] = w[v][u]= ;
de[sccno[u]]++;
de[sccno[v]]++;
}
}
int num=;
for(i = ; i <= scc ; i++)
if(de[i]==) num++;
cout<<(num+)/<<endl;
}
return ;
}
上一篇:从0开始学习 GitHub 系列之「05.Git 进阶」


下一篇:oracle——merge