当前位置:编程学习 > C/C++ >>

POJ 3694 LCA

题意:有N台电脑,他们之间有M条无向边。

然后询问,每次在他们之间加一条边,剩余的桥有多少。

 


思路:其实这题都不需要缩点了。。

直接记录每条桥的位置,然后每次询问进行一次LCA,当询问到桥时,桥数减1,下次询问就不会再计数了。

 

#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 500005   
#define N 200005   
#define stop system("pause")   
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] ;  
  
struct Bridge {  
    int s ,e ;  
} bridge[M] ;  
int n , m ;  
int head[N] ,num ;  
int dfn[N] , low[N] ,st[N] ,inst[N] , belong[N] ;  
int dp ,top ,cnt ;  
int bridgenum ;  
int isBridge[N] ;  
int faa[N] ;  
void add(int s ,int e) {  
    ed[num].e = e ;  
    ed[num].sign = 0 ;  
    ed[num].next = head[s] ;  
    head[s] = num ++ ;  
}  
  
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 ;  
    bridgenum = 0 ;  
    mem(isBridge , 0) ;  
}  
  
void tarjan(int now ,int fa) {  
    dfn[now] = low[now] = ++ dp ;  
    st[top ++ ] = now ;  
    inst[now] = 1 ;  
    faa[now] = fa ;  
    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]) {  
                bridge[bridgenum].s = now ;  
                bridge[bridgenum ++ ].e = e ;  
                isBridge[e] = 1 ;  
            }  
        } 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 read() {  
    init() ;  
    while(m -- ) {  
        int a , b ;  
        RD(a) ;  
        RD(b) ;  
        add(a , b) ;  
        add(b , a) ;  
    }  
    for (int i = 1 ; i <= n ; i ++ ) {  
        dp = 0 ,top = 0 ;  
        if(!dfn[i])tarjan(i , -1) ;  
    }  
}  
void LCA(int u ,int v) {  
    if(dfn[u] < dfn[v]) swap(u , v) ;  
    while(dfn[u] > dfn[v]) {  
        if(isBridge[u]) -- bridgenum , isBridge[u] = 0 ;  
        u = faa[u] ;  
    }  
    while(u != v) {  
        if(isBridge[u])-- bridgenum ,isBridge[u] = 0 ;  
        u = faa[u] ;  
        if(isBridge[v])-- bridgenum ,isBridge[v] = 0 ;  
        v = faa[v] ;  
    }  
}  
  
void solve() {  
    read() ;  
    int Q ;  
    RD(Q) ;  
    while( Q -- ) {  
        int a , b ;  
        RD(a) ;  
        RD(b) ;  
        if(belong[a] != belong[b])  
            LCA(a , b) ;  
        printf("%d\n",bridgenum) ;  
  
    }  
}  
int main() {  
    int cas = 0 ;  
    while(scanf("%d%d",&n ,&m) ,(n + m )) {  
        printf("Case %d:\n",++ cas) ;  
        solve() ;  
        puts("") ;  
    }  
    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 500005
#define N 200005
#define stop system("pause")
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] ;

struct Bridge {
    int s ,e ;
} bridge[M] ;
int n , m ;
int head[N] ,num ;
int dfn[N] , low[N] ,st[N] ,inst[N] , belong[N] ;
int dp ,top ,cnt ;
int bridgenum ;
int isBridge[N] ;
int faa[N] ;
void add(int s ,int e) {
    ed[num].e = e ;
    ed[num].sign = 0 ;
    ed[num].next = head[s] ;
    head[s] = num ++ ;
}

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 ;
    bridgenum = 0 ;
    mem(isBridge , 0) ;
}

void tarjan(int now ,int fa) {
    dfn[now] = low[now] = ++ dp ;
    st[top ++ ] = now ;
    inst[now] = 1 ;
    faa[now] = fa ;
    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]) {
                bridge[bridgenum].s = now ;
                bridge[bridgenum ++ ].e = e ;
                isBridge[e] = 1 ;
            }
        } 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 read() {
    init() ;
    while(m -- ) {
        int a , b ;
        RD(a) ;
        RD(b) ;
        add(a , b) ;
        add(b , a) ;
    }
    for (int i = 1 ; i <= n ; i ++ ) {
        dp = 0 ,top = 0 ;
        if(!dfn[i])tarjan(i , -1) ;
    }
}
void LCA(int u ,int v) {
    if(dfn[u] < dfn[v]) swap(u , v) ;
    while(dfn[u] > dfn[v]) {
        if(isBridge[u]) -- bridgenum , isBridge[u] = 0 ;
        u = faa[u] ;
    }
    while(u != v) {
        if(isBridge[u])-- bridgenum ,isBridge[u] = 0 ;
        u = faa[u] ;
        if(isBridge[v])-- bridgenum ,isBridge[v] = 0 ;
        v = faa[v] ;
    }
}

void solve() {
    read() ;
    int Q ;
    RD(Q) ;
    while( Q -- ) {
        int a , b ;
        RD(a) ;
        RD(b) ;
        if(belong[a] != belong[b])
            LCA(a , b) ;
        printf("%d\n",bridgenum) ;

    }
}
int main() {
    int cas = 0 ;
    while(scanf("%d%d",&n ,&m) ,(n + m )) {
        printf("Case %d:\n",++ cas) ;
        solve() ;
        puts("") ;
    }
    return 0 ;
}

 

补充:软件开发 , C++ ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,