hdu3394Railway双连通分量+模板详细解释

Posted MissZhou要努力

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu3394Railway双连通分量+模板详细解释相关的知识,希望对你有一定的参考价值。

拖了好久的双联通分量==本来周三那会儿觉得强连通分量挺简单,兴致勃勃的开双连通→_→结果模板研究了两整天@。@

说一下这个题的思路:

这个题简直不科学,题意想让桥作为删的边!(读错了不能怨题)而在双连通图中是边数大于点数的,则所有边都是冲突边==


/**********
hdu3394
2015.11.14
374MS	7448K	2262B
**********/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <stack>

using namespace std;

const int N=10006;
struct Edge

    int st, en;
    Edge() 
    Edge(int a, int b)
    
        st=a, en=b;
    
;
stack <Edge> palm;
vector <int> arc[N];
vector <Edge> block[N];
int dfn[N], low[N];
bool vs[N];
int n, m, ind, T, sum1, sum2;

void tarjan(int u, int pre)

    dfn[u]=low[u]=T++;
    int len=(int)arc[u].size();
    for(int i=0; i<len; i++)
    
        int v=arc[u][i];
        if(dfn[v]==-1)//遍历与此点相连而且没遍历过的点
        
            palm.push(Edge(u, v));//边压入栈
            tarjan(v, u);
            if(low[u]>low[v]) low[u]=low[v];//用子节点的low值更新自己的(low的定义不就是此点以及其后代所能连回的最先祖先的pre值嘛)
            if(dfn[u]<=low[v])//存在子节点连不回此点之前的点则这个点是割顶 d=====( ̄▽ ̄*)b --定理
            
                for(Edge temp; !palm.empty(); )
                
                    temp=palm.top();//
                    if(dfn[temp.st]<dfn[v]) break;
                    block[ind].push_back(temp), palm.pop();
                
                block[ind++].push_back(Edge(u, v));//最后一个压入这个序号为ind的边就是u,v
                palm.pop();
                if(dfn[u]<low[v]) sum1++;//作为割顶的特殊情况 如果v的后代只能连回v自己 那么构成的是桥
            
        
        else if(v!=pre && dfn[v]<dfn[u])
        
            palm.push(Edge(u, v));
            if(low[u]>dfn[v]) low[u]=dfn[v];
        
    


int main()

    while(scanf("%d%d", &n, &m), n!=0 || m!=0)
    
        for(int i=0; i<n; i++) arc[i].clear();
        for(int i=0, a, b; i<m; i++)
        
            scanf("%d%d", &a, &b);
            arc[a].push_back(b);
            arc[b].push_back(a);
        
        for(int i=0; i<n; i++) dfn[i]=-1, block[i].clear();
        while(!palm.empty()) palm.pop();
        ind=T=sum1=sum2=0;
        for(int i=0; i<n; i++) if(dfn[i]==-1) tarjan(i, -1);
        for(int i=0; i<ind; i++)
        
            for(int j=0; j<n; j++) vs[j]=0;
            int len=(int)block[i].size(), tot=0;
            for(int j=0; j<len; j++)
            
                if(!vs[block[i][j].st]) vs[block[i][j].st]=1, tot++;
                if(!vs[block[i][j].en]) vs[block[i][j].en]=1, tot++;
            
            if(len>tot) sum2+=len;
        
        printf("%d %d\\n", sum1, sum2);
    
    return 0;




以上是关于hdu3394Railway双连通分量+模板详细解释的主要内容,如果未能解决你的问题,请参考以下文章

hdu4612-Warm up(边的双连通分量)

HDU3394Railway

HDU3394:Railway

连通图(Tarjan算法) 专题总结

双连通分量

HDU 3749 Financial Crisis(点-双连通分量)