zoukankan      html  css  js  c++  java
  • HDU 4612 (13年多校第二场1002)无向图缩点,有重边

    这道题是多校的题,比赛的时候是一道纷纷水过的板刷题。

    题意:给你一些无向边,只加一条边,使该图的桥最少,然后输出最少的桥。

    思路:当时大致想到思路了,就是缩点之后找出最长的链,然后用总的桥数减去链上的桥数。

    也是这么写的,但是卡在了重边上。。

    还是接触的题目太少了。。

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <string>
    #include <cmath>
    #include <cstring>
    #include <queue>
    #include <set>
    #include <vector>
    #include <stack>
    #include <map>
    #include <iomanip>
    #define PI acos(-1.0)
    #define Max 2505
    #define inf 1<<28
    #define LL(x) ( x << 1 )
    #define RR(x) ( x << 1 | 1 )
    #define REP(i,s,t) for( int i = ( s ) ; i <= ( t ) ; ++ i )
    #define ll long long
    #define mem(a,b) memset(a,b,sizeof(a))
    #define mp(a,b) make_pair(a,b)
    #define PII pair<int,int>
    using namespace std;
    #define M 2000005
    #define N 200005
    #pragma comment(linker,"/STACK:102400000,102400000")
    
    inline void RD(int &ret) {
        char c;
        do {
            c = getchar();
        } while(c < '0' || c > '9') ;
        ret = c - '0';
        while((c=getchar()) >= '0' && c <= '9')
            ret = ret * 10 + ( c - '0' );
    }
    struct edge{
        int e , next , sign ;
    }ed[M] ,reed[M] ;
    int n , m ;
    int head[N] ,num ,rehead[N] ,renum ;
    int dfn[N] , low[N] ,st[N] ,inst[N] , belong[N] ;
    int dp ,top ,cnt ;
    int dis[N] ;
    bool vis[N] ;
    int bridgenum ;
    void add(int s ,int e){
        ed[num].e = e ;
        ed[num].sign = 0 ;
        ed[num].next = head[s] ;
        head[s] = num ++ ;
    }
    void readd(int s ,int e){
        reed[renum].e = e ;
        reed[renum].sign = 0 ;
        reed[renum].next = rehead[s] ;
        rehead[s] = renum ++ ;
    }
    void init(){
        mem(dfn, 0) ;
        mem(low , 0) ;
        mem(st ,0) ;
        mem(belong ,0) ;
        mem(head, -1) ;
        num = 0 ;
        dp = 0 ;
        top = 0 ;
        cnt = 0 ;
        mem(rehead,-1) ;
        renum = 0 ;
        bridgenum = 0 ;
    }
    
    void tarjan(int now ,int fa){
        dfn[now] = low[now] = ++ dp ;
        st[top ++ ] = now ;
        inst[now] = 1 ;
    
        for (int i = head[now] ; ~i ; i = ed[i].next ){
            if(ed[i].sign)continue ;
            ed[i].sign = ed[i ^ 1].sign = 1 ;
            int e = ed[i].e ;
            if(!dfn[e]){
                tarjan(e , now) ;
                low[now] = min(low[now] ,low[e]) ;
                if(dfn[now] < low[e]){
                    bridgenum ++ ;
                }
            }
            else if(inst[e]){
                low[now] = min(low[now] , dfn[e]) ;
            }
        }
        if(low[now] == dfn[now]){
            int xx ;
            cnt ++ ;
            do{
                xx = st[-- top] ;
                inst[xx] = 0 ;
                belong[xx] = cnt ;
            }while(xx != now) ;
        }
    }
    
    void build(){
        for (int i = 1 ; i <= n ; i ++ ){
            dp = 0 ,top = 0 ;
            if(!dfn[i]){
                tarjan(i ,-1) ;
            }
        }
        for (int i = 1 ; i <= n ; i ++ ){
            for (int j = head[i] ; ~j ; j = ed[j].next ){
                int e = ed[j].e ;
                if(belong[i] == belong[e])continue ;
                readd(belong[i] , belong[e]) ;
                readd(belong[e] ,belong[i]) ;
            }
        }
    }
    queue<int>qe ;
    int pos ;
    int bfs(int s){
        while(!qe.empty())qe.pop() ;
        dis[s] = 0 ;
        mem(vis , 0) ;
        vis[s] = 1 ;
        qe.push(s) ;
        int ans = 0 ;
        while(!qe.empty()){
            int temp = qe.front() ;
            qe.pop() ;
            for (int i = rehead[temp] ; ~i ; i = reed[i].next){
                int e = reed[i].e ;
                if(!vis[e]){
                    dis[e] = dis[temp] + 1 ;
                    vis[e] = 1 ;
                    qe.push(e) ;
                    if(ans < dis[e]){
                        ans = dis[e] ;
                        pos = e ;
                    }
                }
            }
        }
        return ans ;
    }
    int main() {
        while(scanf("%d%d",&n,&m) , (n + m)){
            init() ;
            while(m -- ){
                int a , b ;
                RD(a) ;RD(b) ;
                add(a , b) ;
                add(b , a) ;
            }
            build() ;
            bfs(1) ;
            int now = bfs(pos) ;
            printf("%d
    ",bridgenum - now) ;
        }
        return 0 ;
    }
    


  • 相关阅读:
    小猫爬山
    方格取数
    Bash 脚本编程
    树链剖分学习笔记
    输入输出优化
    没有上司的舞会
    线性dp 之 麻烦的聚餐
    飞翔
    挖地雷
    The Prices
  • 原文地址:https://www.cnblogs.com/riskyer/p/3217811.html
Copyright © 2011-2022 走看看