您的位置:首页 > Web前端 > Node.js

【割点 && dfs】UVALive - 7456 Least Crucial Node

2017-08-23 14:07 288 查看
Problem Description

给你n,s,m分别代表n个点,s为特殊点,m条边。让你求去掉那个点?使得其他点不能到达s点的点最多。如果存在割点,一样多的。输出编号最小的。

思路:

割点的条件, low[to] >= low[u],u就是割点。所以我们求出割点后,我们可以根据这个条件去dfs,low[to]>=low[u]的to点,这些点都不能到达特殊点。我们记录个数。求出最大个数对应的割点(编号最小)。还有一个割点条件,就是根结点是割点,这个题目如果根结点是割点直接输出1就好了。

#include<bits/stdc++.h>
using namespace std;
struct node
{
int to, next;
};
node Map[100055];
int head[100055], low[150], dfn[150], flag[150], vis[150];
int inde, s;
void dfs(int u, int father)//求割点,用flag[]标记起来
{
int child = 0;
low[u] = dfn[u] = inde++;
for(int i = head[u]; ~i; i = Map[i].next)
{
int to = Map[i].to;
if(!dfn[to])
{
child++;
dfs(to, u);
low[u] = min(low[u], low[to]);
if(u != s && low[to] >= dfn[u])//儿子回不到祖先,代表父亲是割点
{
flag[u] = 1;
}
if(u == s && child == 2)//根结点,有两个儿子的话,自己就是割点
flag[u] = 1;
}
else if(to != father)//这句话可以不用。
{
low[u] = min(low[u], dfn[to]);
}
}
return;
}
int ddf(int u, int ff)//求该割点分离了多少个点,
{
vis[u] = 1;
int red = 0;
for(int i = head[u]; ~i; i = Map[i].next)
{
int to = Map[i].to;
if(low[to] >= dfn[ff] && !vis[to])//满足割点条件继续走
{
red = ddf(to, ff) + 1;
}
}
return red;//返回分离了多少个点
}
void add(int u, int v, int &cnt)
{
Map[cnt].to = v;
Map[cnt].next = head[u];
head[u] = cnt++;
}
int main()
{
int n, m, u, v;
while(~scanf("%d", &n) && n)
{
scanf("%d %d", &s, &m);
int cnt = 0;
memset(head, -1, sizeof(head));
memset(flag, 0, sizeof(flag));
memset(dfn, 0, sizeof(dfn));
while(m--)
{
scanf("%d %d", &u, &v);
add(u, v, cnt);
add(v, u, cnt);
}
inde = 1;
dfs(s, s);
int Max = 0, sum, ans = 1;
for(int i = 1; i <= n; i++)//求分离最多点的割点。同样多的话,选择编号最小的。
{
if(flag[i] == 1)
{
memset(vis, 0, sizeof(vis));
sum = ddf(i, i);
if(sum > Max)
{
Max = sum;
ans = i;
}
}
}
printf("%d\n", ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: