POJ 1236 Network of Schools(tarjan算法 + LCA)

  这个题目网上有很多答案,代码也很像,不排除我的。大家的思路应该都是taijan求出割边,然后找两个点的LCA(最近公共祖先),这两个点和LCA以及其他点构成了一个环,我们判断这个环上的割边有几条,我们的答案就少几个。

  有人问,这个题重边怎么办呢,重边肯定不是桥啊。额……对于这个我只能说,这个题的原始图应该是没有重边的,后来加的边可能会有重边,不过不影响我们的判断,因为我们通过标记点的方式去判的。(这个题还是应该说明一下啊,题目有点问题……)。

  其次,这个题的好玩之处来了,网上人分享的代码,居然过不了一组很简单的样例(如下),(现在大多人可能已经修正了),其实这个原因我应该是找到了,那就是dfn(出生日期)和deep(深搜的层数)的使用错误,当你使用deep的时候交换两者的值是没错的,因为我们总能让他们调整到一层上,然后他们的LCA也一定在一层上了,使用fa数组可以追溯到他们的LCA。然而如果是用dfn交换两者的值就是错误的了,因为即使你调整了他们的值满足一定的大小关系,他们也不一定在一层上,很有可能追溯到了环的外面,所以在追溯的时候很可能会多减上几条边。也就是出现了下面的样例,答案是1,有人输出了0;

  其实这个地方我一直有一个疑惑,那就是使用dfn判断的时候,最后的时候居然会出现二者不相等的情况,这与深搜的性质相违背,到现在也没找到一个样例可以说明他是正确的,我确实感觉到当判断完前两个循环的时候dfn【u】就是他们的LCA了,这个疑惑我先放到这里,便于以后解答,在以后我会主要选择记录深度的方法去做,比较好理解,比较保险(就如我下面代码里的方法)

  附:这个题还有一个解决方法,就是求双连通分量,通过判断两点是否在一个分量里判断两点之间的边是否为桥,然后再合并这两个点。求连通分量的办法一种是并查集,在判断的时候合并到一个集合里,一种是栈的储存方式,id数组,与有向图求强连通分量的方法一致。注意无向图的双连通分量不是指能否相互到达,而是指这个分量里面不含桥,所以当两个点不在一个集合中的时候,这条边一定就是桥。

6 5
1 2
2 3
2 4
3 5
4 6
1
5 6

答案:1

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define maxn 100010
int head[maxn],dfn[maxn],low[maxn],fa[maxn],deep[maxn];
int all,tot,bridge[maxn],brinum;
struct Edge
{
    int to,nxt;
} edge[4*maxn];
void addadge(int a,int b)
{
    edge[tot].to = b;
    edge[tot].nxt = head[a];
    head[a] = tot++;
}
void dfs(int u,int pa)
{
    low[u] = dfn[u] = ++all;
    deep[u] = deep[pa] + 1;
    for(int i = head[u]; i != -1; i = edge[i].nxt)
    {
        int v = edge[i].to;
        if(!dfn[v])
        {
            fa[v] = u;
            dfs(v,u);
            low[u] = min(low[u],low[v]);
            if(low[v] > dfn[u])
            {
                bridge[v] = 1;
                brinum++;
            }
        }
        else if(v != pa) low[u] = min(low[u],dfn[v]);
    }
}
void lca(int a,int b)
{
    while(deep[a] > deep[b])
    {
        if(bridge[a])
        {
            bridge[a] = 0;
            brinum--;
        }
        a = fa[a];
    }
    while(deep[b] > deep[a])
    {
        if(bridge[b])
        {
            bridge[b] = 0;
            brinum--;
        }
        b = fa[b];
    }
    while(a != b)
    {
        if(bridge[a])
        {
            bridge[a] = 0;
            brinum--;
        }
        if(bridge[b])
        {
            bridge[b] = 0;
            brinum--;
        }
        a = fa[a];
        b = fa[b];
    }
}
int main()
{
    int n,m,q,a,b,ca = 0;
    while(~scanf("%d%d",&n,&m))
    {
        if(!n && !m) break;
        for(int i = 0; i <= n; i++)
        {
            head[i] = -1;
            dfn[i] = 0;
            low[i] = 0;
            fa[i] = i;
            deep[i] = 0;
            bridge[i] = 0;
        }
        tot = 0;
        all = 0;
        brinum = 0;
        for(int i = 0; i < m; i++)
        {
            scanf("%d%d",&a,&b);
            addadge(a,b);
            addadge(b,a);
        }
        dfs(1,1);
        scanf("%d",&q);
        printf("Case %d:\n",++ca);
        while(q--)
        {
            scanf("%d%d",&a,&b);
            lca(a,b);
            printf("%d\n",brinum);
        }
        puts("");
    }
    return 0;
}
时间: 2024-10-18 01:35:15

POJ 1236 Network of Schools(tarjan算法 + LCA)的相关文章

Poj 1236 Network of Schools (Tarjan)

题目链接: Poj 1236 Network of Schools 题目描述: 有n个学校,学校之间有一些单向的用来发射无线电的线路,当一个学校得到网络可以通过线路向其他学校传输网络,1:至少分配几个网络才能够让所有学校被网络覆盖?2:至少要加几条线路就能做到在任意一个学校安装网络都可以覆盖全部学校? 解题思路: 先用Tarjan对强连通分量进行缩点,然后对缩点以后的图进行处理,统计图中节点出度为零的有多少,入度为零的有多少个? 因为入度为零的点不能由其他的点到达,在每个入度为零的节点安装网络可

POJ 1236 Network of Schools (Tarjan + 缩点)

Network of Schools Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 12240   Accepted: 4871 Description A number of schools are connected to a computer network. Agreements have been developed among those schools: each school maintains a li

POJ 1236 Network of Schools(强连通 Tarjan+缩点)

POJ 1236 Network of Schools(强连通 Tarjan+缩点) ACM 题目地址:POJ 1236 题意: 给定一张有向图,问最少选择几个点能遍历全图,以及最少加入?几条边使得有向图成为一个强连通图. 分析: 跟HDU 2767 Proving Equivalences(题解)一样的题目,只是多了个问题,事实上转化成DAG后就不难考虑了,事实上仅仅要选择入度为0的点即可了. 代码: /* * Author: illuz <iilluzen[at]gmail.com> *

POJ 1236 Network of Schools(强连通分量)

POJ 1236 Network of Schools 链接:http://poj.org/problem?id=1236 题意:有一些学校连接到一个计算机网络.这些学校之间达成了一个协议:每个学校维护着一个学校列表,它向学校列表中的学校发布软件.注意,如果学校B 在学校A 的列表中,则A 不一定在B 的列表中. 任务A:计算为使得每个学校都能通过网络收到软件,你至少需要准备多少份软件拷贝. 任务B:考虑一个更长远的任务,想确保给任意一个学校发放一个新的软件拷贝,该软件拷贝能发布到网络中的每个学

poj 1236 Network of Schools 【强连通图】

题目:poj 1236 Network of Schools 类似题目hdoj 2767 3836 /*******以下kuang大神的解释,写的很好就不解释了*************************/ 强连通分量缩点求入度为0的个数和出度为0的分量个数 题目大意:N(2<N<100)各学校之间有单向的网络,每个学校得到一套软件后,可以通过单向网络向周边的学校传输,问题1:初始至少需要向多少个学校发放软件,使得网络内所有的学校最终都能得到软件.2,至少需要添加几条传输线路(边),使任

[tarjan] poj 1236 Network of Schools

题目链接: http://poj.org/problem?id=1236 Network of Schools Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 11433   Accepted: 4551 Description A number of schools are connected to a computer network. Agreements have been developed among thos

poj 1236 Network of Schools(连通图入度,出度为0)

http://poj.org/problem?id=1236 Network of Schools Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 13046   Accepted: 5215 Description A number of schools are connected to a computer network. Agreements have been developed among those scho

poj 1236 Network of Schools(tarjan+缩点)

Network of Schools Description A number of schools are connected to a computer network. Agreements have been developed among those schools: each school maintains a list of schools to which it distributes software (the “receiving schools”). Note that

POJ 1236——Network of Schools——————【加边形成强连通图】

Network of Schools Time Limit:1000MS     Memory Limit:10000KB     64bit IO Format:%I64d & %I64u Submit Status Practice POJ 1236 Description A number of schools are connected to a computer network. Agreements have been developed among those schools: e

POJ 1236 Network of Schools 强连通图

Description A number of schools are connected to a computer network. Agreements have been developed among those schools: each school maintains a list of schools to which it distributes software (the "receiving schools"). Note that if B is in the