您的位置:首页 > 其它

【POJ3352】Road Construction(边双联通分量)

2016-09-26 20:57 351 查看

题意:给一个无向图,问最少添加多少条边后能使整个图变成双连通分量。

思路:双连通分量缩点,缩点后给度为1的分量两两之间连边,要连(ans+1) div 2条

         low[u]即为u所在的分量编号,flag=0,1,2表示没搜过,没搜完,搜完了

POJ上pascal编译器出问题了不管怎么交都CE

这次写的 应该能处理重边

var head,vet,next,flag,dfn,low,fan,de:array[0..10000]of longint;
n,m,i,e,v,ans,x,y,tot,time:longint;

procedure add(a,b:longint);
begin
inc(tot);
next[tot]:=head[a];
vet[tot]:=b;
head[a]:=tot;
end;

function min(x,y:longint):longint;
begin
if x<y then exit(x);
exit(y);
end;

procedure dfs(u,le:longint);
var e,v:longint;
begin
flag[u]:=1;
inc(time); dfn[u]:=time; low[u]:=time;
e:=head[u];
while e<>0 do
begin
v:=vet[e];
if e=fan[le] then
begin
e:=next[e];
continue;
end;
if flag[v]=0 then
begin
dfs(v,e);
low[u]:=min(low[u],low[v]);
end
else if flag[v]=1 then low[u]:=min(low[u],dfn[v]);
e:=next[e];
end;
flag[u]:=2;
end;

begin

for i:=0 to 2000 do
if i mod 2=1 then fan[i]:=i+1
else fan[i]:=i-1;
while not eof do
begin
readln(n,m);
if (n=0)and(m=0) then break;
fillchar(head,sizeof(head),0);
fillchar(low,sizeof(low),0);
fillchar(de,sizeof(de),0);
fillchar(flag,sizeof(flag),0);
tot:=0; time:=0;
for i:=1 to m do
begin
read(x,y);
add(x,y);
add(y,x);
end;
for i:=1 to n do
if flag[i]=0 then dfs(i,0);
for i:=1 to n do
begin
e:=head[i];
while e<>0 do
begin
v:=vet[e];
if low[v]<>low[i] then inc(de[low[i]]);
e:=next[e];
end;
end;
ans:=0;
for i:=1 to n do
if de[i]=1 then inc(ans);
writeln((ans+1) div 2);
end;

end.

这个是去年写的那时候AC了 好像不能处理重边

var de,low,next,vet,head,flag,dfn:array[1..10000]of longint;
n,m,tot,x,y,i,e,v,leaf,time:longint;

function min(x,y:longint):longint;
begin
if x<y then exit(X);
exit(y);
end;

procedure add(a,b:longint);
begin
inc(tot);
next[tot]:=head[a];
vet[tot]:=b;
head[a]:=tot;
end;

procedure dfs(u,fa:longint);
var e,v:longint;
begin
inc(time);
dfn[u]:=time; low[u]:=time;
flag[u]:=1;
e:=head[u];
while e<>0 do
begin
v:=vet[e];
if v=fa then
begin
e:=next[e];
continue;
end;
if flag[v]=0 then
begin
dfs(v,u);
low[u]:=min(low[u],low[v]);
end
else if flag[v]=1 then low[u]:=min(low[u],dfn[v]);
e:=next[e];
end;
flag[u]:=2;
end;

begin

while not eof do
begin
readln(n,m);
if (n=0)and(m=0) then break;
fillchar(head,sizeof(head),0);
tot:=0;
for i:=1 to m do
begin
readln(x,y);
add(x,y);
add(y,x);
end;
fillchar(dfn,sizeof(dfn),0);
fillchar(de,sizeof(de),0);
fillchar(flag,sizeof(flag),0);
time:=0;
for i:=1 to n do
if flag[i]=0 then dfs(i,i);
for i:=1 to n do
begin
e:=head[i];
while e<>0 do
begin
v:=vet[e];
if low[i]<>low[v] then inc(de[low[i]]);
e:=next[e];
end;
end;
leaf:=0;
for i:=1 to n do
if de[i]=1 then inc(leaf);
writeln((leaf+1) div 2);
end;

end.

 UPD(2018.10.18):C++

#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
#include<vector>
using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
typedef pair<int,int> PII;
typedef vector<int> VI;
#define fi first
#define se second
#define MP make_pair
#define N   15000
#define M   6100000
#define eps 1e-8
#define pi  acos(-1)
#define oo  1e9

int head
,vet
,nxt
,flag
,dfn
,low
,fan
,d
,
tot,tim;

void add(int a,int b)
{
nxt[++tot]=head[a];
vet[tot]=b;
head[a]=tot;
}

void dfs(int u,int le)
{
flag[u]=1;
dfn[u]=low[u]=++tim;
int e=head[u];
while(e)
{
int v=vet[e];
if(e==fan[le])
{
e=nxt[e];
continue;
}
if(!flag[v])
{
dfs(v,e);
low[u]=min(low[u],low[v]);
}
else if(flag[v]==1) low[u]=min(low[u],dfn[v]);
e=nxt[e];
}
flag[u]=2;
}

int main()
{
freopen("poj3352.in","r",stdin);
freopen("poj3352.out","w",stdout);
for(int i=0;i<=2000;i++)
if(i&1) fan[i]=i+1;
else fan[i]=i-1;
int n,m;
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(head,0,sizeof(head));
memset(low,0,sizeof(low));
memset(d,0,sizeof(d));
memset(flag,0,sizeof(flag));
tot=tim=0;
for(int i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
for(int i=1;i<=n;i++)
if(flag[i]==0) dfs(i,0);
for(int i=1;i<=n;i++)
{
int e=head[i];
while(e)
{
int v=vet[e];
if(low[v]!=low[i]) d[low[i]]++;
e=nxt[e];
}
}
int ans=0;
for(int i=1;i<=n;i++)
if(d[i]==1) ans++;
printf("%d\n",(ans+1)/2);
}
return 0;
}

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: