HDU 3394 Railway (点双联通+圈内判边数)

大意:给定M条边,问有有多少边是不在环上(或环内)的,有多少边是有冲突的(什么是冲突?即在一个环内有多条边将环分割开,即这样的边+上环上边的总数)

思路:求桥的个数比较容易处理,直接(low[v]>dfn[u]即可)主要是怎么找冲突边,我们知道他们一定在一个联通分量内,所以我们将求出的 一组联通分量拿出来,进行遍历看是否所有的连的边在当前的栈中,在的话边数++,因为是无向图,所以最后要除二与联通分量的点相比较即可。

前向星:

#include<map>
#include<queue>
#include<cmath>
#include<cstdio>
#include<stack>
#include<iostream>
#include<cstring>
#include<algorithm>
#define LL int
#define inf 0x3f3f3f3f
#define eps 1e-8
#include<vector>
#define ls l,mid,rt<<1
#define rs mid+1,r,rt<<1|1
using namespace std;
const int Ma = 21000;
struct node{
    int to,next;
}q[Ma*10];//注意看题目边的数目*2
int head[Ma*10],dfn[Ma],num[Ma],stk[Ma],du[Ma],low[Ma];
int cnt,top,tim,scc,sum,n,tmp[Ma],S,CNT,ans;
bool vis[Ma],bj[Ma];

void Add(int a,int b){
    q[cnt].to = b;
    q[cnt].next = head[a];
    head[a] = cnt++;
}

void init(){
    ans = CNT  = scc = cnt = top = 0;
    tim =  1;
    memset(head,-1,sizeof(head));
    for(int i = 0;i < n;++ i){
        num[i] = low[i]  = dfn[i] = 0;
        du[i] = vis[i]  = 0;
    }
}
void Judge(){
    int E = 0;
    for(int i = 0;i < S;++ i){
        int u = tmp[i];
        for(int j = head[u];~j;j=q[j].next){
            int v = q[j].to;
            if( bj[v] ){
                E++;

            }
        }
    }
    E /= 2;
    if(E > S)
        CNT += E;
}

void Tarjan(int u,int To){
    low[u] = dfn[u] = tim++;
    vis[u] = true;
    stk[top++] = u;

    for(int i = head[u]; ~i ; i = q[i].next){
        int v = q[i].to;
        if(i == (To^1)) continue;
        if(!vis[v]){
            Tarjan(v,i);
            low[u] = min(low[u],low[v]);
            if(low[v]>dfn[u])
                ans++;
            if(low[v] >= dfn[u]){
                memset(bj,false,sizeof(bj));
                S = 0;
                stk[top] = -1;
                tmp[S++] = u;bj[u] = true;
                while(stk[top] != v){
                    int now = stk[--top];
                    tmp[S++] = now;
                    bj[now] = true;
                }
                Judge();
            }
        }
        else
            low[u] = min(low[u],dfn[v]);
    }
}
int main(){
    int m,i,j,k,a,b;
    while(~scanf("%d%d",&n,&m)){
        if(!n&&!m) break;
        init();
        for(i = 0;i < m;++ i){
            scanf("%d%d",&a,&b);
            Add(a,b);Add(b,a);
        }

        for(i = 0;i < n;++ i)
            if(!dfn[i])
                Tarjan(i,-1);
        printf("%d %d\n",ans,CNT);
    }
    return 0;
}
时间: 2024-10-13 17:16:36

HDU 3394 Railway (点双联通+圈内判边数)的相关文章

HDU 3394 Railway(点双连通分量的应用)

题意:给定一个无向图,分别求出不在任何环中的边的数量和同时在两个或以上的环中的边的数量. 解法:桥上的边就是不在任何环中的.而如果一个点双连通分量中边的数量比点的数量要多,那么该双连通分量的所有边都同时在两个或以上的环中(这个可以想象一下,在一个简单环中多加一条端点不同的边,这样简单环就会被分割成两个小的简单环,任何一条在大的环中的边都会同时处于一个其中一个小的环中). 在tarjan算法中,当lowv>pre[u]时(u是起始点,v是边的下一个点),边(u,v)就是一条桥.而点双连通分量的边的

【POJ 2942】Knights of the Round Table(双联通分量+染色判奇环)

[POJ 2942]Knights of the Round Table(双联通分量+染色判奇环) Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 11661   Accepted: 3824 Description Being a knight is a very attractive career: searching for the Holy Grail, saving damsels in distress, an

Railway HDU - 3394 (点双连通)

Railway HDU - 3394 题意:一个无向图,1求不在任何一个环里的边数:2求在不止一个环里的边数. 第一问明显就是求桥,第二问,如果求出的某个点双连通分量里面边数多于点数,说明不止一个环,那么所有的边都在不止一个环里. 该求点双连通的,,求成了边双连通...要仔细分析问题. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <vector> 5 us

HDU - 3394 Railway(连通分量+环)

题目大意:有一个人奇怪的人想要铺路,这个人想把每个环都铺上石头,但是铺石头时不能重复铺,如果重复铺的话,这条边就算损坏 问这个人要损坏多少条边,有多少条边可以不用铺石头 解题思路:不用铺石头的边肯定是桥,因为桥不属于任意一个环 接着判断一下有多少条边会冲突,首先,一个环的话肯定是点-双连通,但点-双连通不一定是个环,所以这个要判断一下. 一个正常的环是要满足 边数=点数 的,如果边数比点数多了,证明这个环被分割成至少三个环了(一个最外围的环,两个被分的小环),可以看出,这三个环每条边都冲突 所以

HDU 4738 --Caocao&#39;s Bridges 【无向图边双联通 &amp;&amp; 求权值最小的桥 &amp;&amp; 模板】

Caocao's Bridges Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2641    Accepted Submission(s): 855 Problem Description Caocao was defeated by Zhuge Liang and Zhou Yu in the battle of Chibi. B

HDU 4738 Caocao&#39;s Bridges(双联通分量+并查集)

大意:有n座岛和m条桥,每条桥上有w个兵守着,现在要派不少于守桥的士兵数的人去炸桥,只能炸一条桥,使得这n座岛不连通,求最少要派多少人去. 思路:我们就是要缩点后直接求桥上人的最少数量.(PS:1.注意图如果不联通直接输出0.2.如果图中的桥上人为0,个那么要让一个人去.3.重边的问题.这里可以忽略) #include<map> #include<queue> #include<cmath> #include<cstdio> #include<stac

HDU 4612 Warm up(边双联通求树的直径)

Problem Description N planets are connected by M bidirectional channels that allow instant transportation. It's always possible to travel between any two planets through these channels. If we can isolate some planets from others by breaking only one

HDU 4612 双联通分量+树的直径

点击打开链接 题意:给一个无向联通图,里面可能有重边,问添加一条边后,使得图中的桥最小,将桥的数量输出 思路:刚刚读完题,就有了思路去写,无非就是将联通图双联通分量后缩点,然后求一条最长的路,首尾相连,肯定将更多的桥包含使得这些桥不再是桥,很好想的题,但是错了20+什么鬼,md重边这么难处理,醉了~~~,之前的做法是将重边全部找出来,希望数据弱点水过去算了,TLE好样的,那么我们在处理桥的时候,也就是找桥的时候,如果是桥,我们将这条边标记一下,然后找所有边时加上就行了,在一个就是找树的直径,两次

hihocoder #1190 : 连通性&#183;四 点双联通分量

http://hihocoder.com/problemset/problem/1190?sid=1051696 先抄袭一下 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho从约翰家回到学校时,网络所的老师又找到了小Hi和小Ho. 老师告诉小Hi和小Ho:之前的分组出了点问题,当服务器(上次是连接)发生宕机的时候,在同一组的服务器有可能连接不上,所以他们希望重新进行一次分组.这一次老师希望对连接进行分组,并把一个组内的所有连接关联的服务器也视为这个组内