POJ3352(连通分量缩点)

Road Construction

Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 10352   Accepted: 5140

Description

It‘s almost summer time, and that means that it‘s almost summer construction time! This year, the good people who are in charge of the roads on the tropical island paradise of Remote Island would like to repair and upgrade the various roads that lead between the various tourist attractions on the island.

The roads themselves are also rather interesting. Due to the strange customs of the island, the roads are arranged so that they never meet at intersections, but rather pass over or under each other using bridges and tunnels. In this way, each road runs between two specific tourist attractions, so that the tourists do not become irreparably lost.

Unfortunately, given the nature of the repairs and upgrades needed on each road, when the construction company works on a particular road, it is unusable in either direction. This could cause a problem if it becomes impossible to travel between two tourist attractions, even if the construction company works on only one road at any particular time.

So, the Road Department of Remote Island has decided to call upon your consulting services to help remedy this problem. It has been decided that new roads will have to be built between the various attractions in such a way that in the final configuration, if any one road is undergoing construction, it would still be possible to travel between any two tourist attractions using the remaining roads. Your task is to find the minimum number of new roads necessary.

Input

The first line of input will consist of positive integers n and r, separated by a space, where 3 ≤ n ≤ 1000 is the number of tourist attractions on the island, and 2 ≤ r ≤ 1000 is the number of roads. The tourist attractions are conveniently labelled from 1 to n. Each of the following r lines will consist of two integers, v and w, separated by a space, indicating that a road exists between the attractions labelled v and w. Note that you may travel in either direction down each road, and any pair of tourist attractions will have at most one road directly between them. Also, you are assured that in the current configuration, it is possible to travel between any two tourist attractions.

Output

One line, consisting of an integer, which gives the minimum number of roads that we need to add.

Sample Input

Sample Input 1
10 12
1 2
1 3
1 4
2 5
2 6
5 6
3 7
3 8
7 8
4 9
4 10
9 10

Sample Input 2
3 3
1 2
2 3
1 3

Sample Output

Output for Sample Input 1
2

Output for Sample Input 2
0题意:给定结点和边的数目,确定一幅无向图,问至少加几条边使图为双连通的。(双连通:图中任意两个结点都有两条或以上不同的路径)思路:利用tarjan算法将图中的双连通部分缩为一点,进而得到一棵树。那么(这棵树的叶子结点数目+1)/2 即为答案。
#include"cstdio"
#include"cstring"
using namespace std;
const int MAXN=1005;
int V,E;
bool mp[MAXN][MAXN];//结点不超过1000用邻接矩阵存储
int index;
int dfn[MAXN],low[MAXN];
int stack[MAXN],top;
int cpnt[MAXN],cnt;
inline int min(int a,int b)
{
    return a > b? b: a;
}
void tarjan(int u,int fa)
{
    stack[top++]=u;
    dfn[u]=low[u]=++index;
    for(int i=1;i<=V;i++)
    {
        if(mp[u][i])
        {
            int v=i;
            if(!dfn[v])
            {
                tarjan(v,u);
                low[u]=min(low[u],low[v]);
            }
            else if(v!=fa)    low[u]=min(low[u],dfn[v]);
        }
    }
    if(low[u]==dfn[u])
    {
        int v;
        cnt++;
        do{
            v=stack[--top];
            cpnt[v]=cnt;
        }while(u!=v);
    }
}
int deg[MAXN];
int seek()
{
    int ans=0;
    for(int i=1;i<=V;i++)
        for(int j=1;j<=V;j++)
            if(mp[i][j]&&cpnt[i]!=cpnt[j])
            {
                deg[cpnt[i]]++;
                deg[cpnt[j]]++;
            }

    for(int i=1;i<=cnt;i++)
        if(deg[i]==2)    ans++;
    return ans;
}
int main()
{
    while(scanf("%d%d",&V,&E)!=EOF)
    {
        memset(mp,false,sizeof(mp));
        memset(dfn,0,sizeof(dfn));
        memset(low,0,sizeof(low));
        top=0;
        cnt=0;
        memset(cpnt,0,sizeof(cpnt));
        memset(deg,0,sizeof(deg));
        for(int i=0;i<E;i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            mp[u][v]=mp[v][u]=true;
        }
        tarjan(1,-1);
        int ans=seek();
        printf("%d\n",(ans+1)/2);

    }
    return 0;
}
时间: 2024-10-19 18:04:45

POJ3352(连通分量缩点)的相关文章

HDU 2242 连通分量缩点+树形dp

题目大意是: 所有点在一个连通图上,希望去掉一条边得到两个连通图,且两个图上所有点的权值的差最小,如果没有割边,则输出impossible 这道题需要先利用tarjan算法将在同一连通分量中的点缩成一个点后,重新构建一幅图,然后利用新建的图进行树形dp解决问题 这道题目需要注意的是可能存在重边,那么子节点回到父节点有两条边及以上的话,就需要对子节点经过父节点的边进行low值更新 tarjan算法学习的网站个人感觉还不错https://www.byvoid.com/blog/scc-tarjan/

poj3177 &amp;&amp; poj3352 边双连通分量缩点

Redundant Paths Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 12676   Accepted: 5368 Description In order to get from one of the F (1 <= F <= 5,000) grazing fields (which are numbered 1..F) to another field, Bessie and the rest of the

POJ 3177 Redundant Paths 边双连通分量+缩点

题目链接: poj3177 题意: 给出一张连通图,为了让任意两点都有两条通路(不能重边,可以重点),至少需要加多少条边 题解思路: 分析:在同一个边双连通分量中,任意两点都有至少两条独立路可达,所以同一个边双连通分量里的所有点可以看做同一个点. 缩点后,新图是一棵树,树的边就是原无向图桥. 现在问题转化为:在树中至少添加多少条边能使图变为双连通图. 结论:添加边数=(树中度为1的节点数+1)/2 具体方法为,首先把两个最近公共祖先最远的两个叶节点之间连接一条边,这样可以把这两个点到祖先的路径上

poj3177(边双连通分量+缩点)

传送门:Redundant Paths 题意:有n个牧场,Bessie 要从一个牧场到另一个牧场,要求至少要有2条独立的路可以走.现已有m条路,求至少要新建多少条路,使得任何两个牧场之间至少有两条独立的路.两条独立的路是指:没有公共边的路,但可以经过同一个中间顶点. 分析:在同一个边双连通分量中,任意两点都有至少两条独立路可达,因此同一个边双连通分量里的所有点可以看做同一个点. 缩点后,新图是一棵树,树的边就是原无向图的桥. 现在问题转化为:在树中至少添加多少条边能使图变为双连通图. 结论:添加

Poj 3352 Road Construction &amp; Poj 3177 Redundant Paths(边双连通分量+缩点)

Road Construction Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 9465   Accepted: 4699 Description It's almost summer time, and that means that it's almost summer construction time! This year, the good people who are in charge of the ro

【HDOJ4612】【双连通分量缩点+找树的直径】

http://acm.hdu.edu.cn/showproblem.php?pid=4612 Warm up Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)Total Submission(s): 8309    Accepted Submission(s): 1905 Problem Description N planets are connected by M bidi

HDU 4612 Warm up(双连通分量缩点+求树的直径)

思路:强连通分量缩点,建立一颗新的树,然后求树的最长直径,然后加上一条边能够去掉的桥数,就是直径的长度. 树的直径长度的求法:两次bfs可以求,第一次随便找一个点u,然后进行bfs搜到的最后一个点v,一定是直径的一个端点(证明从略),第二次以点v为开头进行bfs,求出的最后一个点,就是直径的另一个端点,记录深度就是我们要求的长度.我这里是使用的bfs+dfs,是一样的,少开一个deep数组,节省一下空间吧…… 其实我一开始是不会求的,我以为随便一个叶子节点就可以做端点,交上去WA,当时还好奇感觉

POJ 3177 Redundant Paths(边双连通分量)

[题目链接] http://poj.org/problem?id=3177 [题目大意] 给出一张图,问增加几条边,使得整张图构成双连通分量 [题解] 首先我们对图进行双连通分量缩点, 那么问题就转化为给出一棵树,加边使得其成为边双连通分量的最小边数, 只要从叶节点连一条边到任意节点,那么就可以使得这个叶节点加入到双连通分量中, 那么优先叶节点和叶节点连接,所以其答案为(叶节点+1)/2 [代码] #include <cstdio> #include <algorithm> #in

UESTC 899 方老师和农场 --双连通分量的构造

首先将原图中的连通分量缩点,一定可以将原图缩成一棵树的形式,然后统计这棵树的叶子节点个数,答案就是(leaf+1)/2.这里不再证明,可以画个图看一下. (简单说明一下,首先把两个最近公共祖先最远的两个叶节点之间连接一条边,这样可以把这两个点到祖先的路径上所有点收缩到一起,因为一个形成的环一定是双连通的.然后再找两个最近公共祖先最远的两个叶节点,这样一对一对找完,恰好是(leaf+1)/2次,把所有点收缩到了一起.  --Byvoid) 怎么统计呢?用并查集缩点,可以知道,缩点后留下的边全部是原