PKU 3352(图的关键边)
觉得这道题目蛮有意义的
首先求割边 缩图成树 计算叶子结点与根结点连通所需要添加的最少边既可
#include <iostream>
using namespace std;
//点编号从1开始
typedef struct
{
long v,next;
}Edge;
const long MAXN=2000;
long du[MAXN];
long p[MAXN];
Edge e[MAXN];
long eid;
long dfn[MAXN], low[MAXN], deep, color[MAXN], com;
long n,r;
inline void insert(long from,long to)
{
e[eid].next=p[from];
e[eid].v=to;
p[from]=eid++;
//以下为无向图使用
swap(from, to);
e[eid].next=p[from];
e[eid].v=to;
p[from]=eid++;
}
long min(long a,long b)
{
return a<b?a:b;
}
inline void dfs(int i, int f)
{
dfn[i] = low[i] = ++deep;
long j;
for (j = p[i]; j !=-1; j=e[j].next)
{
int k = e[j].v;
if (!dfn[k])
{
dfs(k, i);
low[i] = min(low[i], low[k]);
}
else if (k != f)
{
low[i] = min(low[i], dfn[k]);
}
}
}
inline void set_color(int i)
{
long j;
for (j = p[i]; j !=-1; j=e[j].next)
{
int k = e[j].v;
if (!color[k])
{
if (low[k] > dfn[i]) color[k] = ++com;
else color[k] = color[i];
set_color(k);
}
}
}
inline void biconnect()
{
deep=0;
dfs(1,-1);
com=1;
color[1]=1;
set_color(1);
}
int main()
{
while(scanf("%ld %ld",&n,&r)!=EOF)
{
long i,j;
memset(p,-1,sizeof(p));
memset(du,0,sizeof(du));
memset(low,0,sizeof(low));
memset(color,0,sizeof(color));
memset(dfn,0,sizeof(dfn));
eid=0;
for(i=0;i<r;++i)
{
long from,to;
scanf("%ld %ld",&from,&to);
insert(from,to);
}
//关键边求解
biconnect();
for (i = 1; i <= n; i++)
{
long a = color[i];
for (j = p[i]; j !=-1; j=e[j].next)
{
long b = color[e[j].v];
if (a != b)
{
++du[a];
}
}
}
long leap = 0;
for (i = 1; i <= com; i++)
{
if (du[i] == 1)
{
++leap;
}
}
printf("%ld\n", (leap+1)/2);
}
return 0;
}
using namespace std;
//点编号从1开始
typedef struct
{
long v,next;
}Edge;
const long MAXN=2000;
long du[MAXN];
long p[MAXN];
Edge e[MAXN];
long eid;
long dfn[MAXN], low[MAXN], deep, color[MAXN], com;
long n,r;
inline void insert(long from,long to)
{
e[eid].next=p[from];
e[eid].v=to;
p[from]=eid++;
//以下为无向图使用
swap(from, to);
e[eid].next=p[from];
e[eid].v=to;
p[from]=eid++;
}
long min(long a,long b)
{
return a<b?a:b;
}
inline void dfs(int i, int f)
{
dfn[i] = low[i] = ++deep;
long j;
for (j = p[i]; j !=-1; j=e[j].next)
{
int k = e[j].v;
if (!dfn[k])
{
dfs(k, i);
low[i] = min(low[i], low[k]);
}
else if (k != f)
{
low[i] = min(low[i], dfn[k]);
}
}
}
inline void set_color(int i)
{
long j;
for (j = p[i]; j !=-1; j=e[j].next)
{
int k = e[j].v;
if (!color[k])
{
if (low[k] > dfn[i]) color[k] = ++com;
else color[k] = color[i];
set_color(k);
}
}
}
inline void biconnect()
{
deep=0;
dfs(1,-1);
com=1;
color[1]=1;
set_color(1);
}
int main()
{
while(scanf("%ld %ld",&n,&r)!=EOF)
{
long i,j;
memset(p,-1,sizeof(p));
memset(du,0,sizeof(du));
memset(low,0,sizeof(low));
memset(color,0,sizeof(color));
memset(dfn,0,sizeof(dfn));
eid=0;
for(i=0;i<r;++i)
{
long from,to;
scanf("%ld %ld",&from,&to);
insert(from,to);
}
//关键边求解
biconnect();
for (i = 1; i <= n; i++)
{
long a = color[i];
for (j = p[i]; j !=-1; j=e[j].next)
{
long b = color[e[j].v];
if (a != b)
{
++du[a];
}
}
}
long leap = 0;
for (i = 1; i <= com; i++)
{
if (du[i] == 1)
{
++leap;
}
}
printf("%ld\n", (leap+1)/2);
}
return 0;
}