程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> HDU 4612 (13年多校第二場1002)無向圖縮點,有重邊

HDU 4612 (13年多校第二場1002)無向圖縮點,有重邊

編輯:C++入門知識

這道題是多校的題,比賽的時候是一道紛紛水過的板刷題。

題意:給你一些無向邊,只加一條邊,使該圖的橋最少,然後輸出最少的橋。

思路:當時大致想到思路了,就是縮點之後找出最長的鏈,然後用總的橋數減去鏈上的橋數。

也是這麼寫的,但是卡在了重邊上。。

還是接觸的題目太少了。。

 

#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\n",bridgenum - now) ;  
    }  
    return 0 ;  
}  

#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\n",bridgenum - now) ;
    }
    return 0 ;
}


 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved