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++ ,