hdu 2460 & poj 3694 Network
http://poj.org/problem?id=3694
http://acm.hdu.edu.cn/showproblem.php?pid=2460
题意:给一个无向图,每加入一条新边后,统计桥的数目。
思路:看完解题报告后,觉得自己傻了,几乎是暴力的方法。
用tarjan先统计图中的每个桥,并标记(以桥的出点作标记,即:uv是桥,标记v),并全部归结到以1为根的树中。
查询的时候用类似并差集的方法,不断向根走,同时检查经过的点是不是桥,当u=v的时候就可以退出了。
PS:如果原图是一线树,每次查询都选择两端点。可以知道时间复杂度为10^8,真不知道这样也可以过,只能说数据水了,或者说每加入一条边,保证可以去掉至少一个桥,但题目没有说。
(杭电上要用非递归写tarjan)

#include<set> #include<map> #include<stack> #include<queue> #include<cmath> #include<bitset> #include<string> #include<climits> #include<cstdio> #include<vector> #include<utility> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #define IN puts("in") #define OUT puts("out") #define FR(x) freopen(x,"r",stdin) #define FW(x) freopen(x,"w",stdout) #define MSET(x,y) memset(x,y,sizeof(x)) #define ST system("pause") using namespace std; const int maxn = 100005; struct nd { int u,v,next; }edge[maxn*6]; int head[maxn],vis[maxn],dfn[maxn],low[maxn],fa[maxn],bs[maxn],st[maxn],cur[maxn]; int ecnt,ans,idx,tp; void init() { ecnt = ans = idx = tp = 0; MSET(head,-1); MSET(vis,0); MSET(dfn,0); MSET(bs,0); } void add(int u,int v) { if(u==v)return; edge[ecnt].u = u; edge[ecnt].v = v; edge[ecnt].next = head[u]; head[u] = ecnt++; } void Read(int n) { int i,u,v; for(i = 0; i < n; ++ i){ scanf("%d %d",&u,&v); add(u,v); add(v,u); } } void tarjan() { for(int i = 1; i < maxn; ++ i) cur[i] = head[i]; st[++tp] = 1; while(tp){ int k = st[tp]; if(!vis[k]) { dfn[k] = low[k] = ++ idx; vis[k] = 1;} for(;cur[k]!=-1; cur[k]=edge[cur[k]].next) { int v = edge[cur[k]].v; if(!vis[v]){ fa[v] = k; break; }else if(vis[v]==1&&v!=fa[k]) low[k]=min(dfn[v],low[k]); } if((cur[k]==-1)&&tp>1){ low[st[tp-1]] = min(low[k],low[st[tp-1]]); if(low[k]>dfn[st[tp-1]]){ bs[k] = 1; ans++; } } if(cur[k]==-1){ vis[k] = 2; tp--; }else st[++tp] = edge[cur[k]].v; } } void LCA(int x,int y) { if(dfn[x]<dfn[y]) swap(x,y); while(dfn[x] > dfn[y]){ if(bs[x])ans--,bs[x] = 0; x = fa[x]; } while(x!=y){ if(bs[x])ans--,bs[x] = 0; if(bs[y])ans--,bs[y] = 0; x = fa[x]; y = fa[y]; } } void processing() { int q,u,v; scanf("%d",&q); tarjan(); while(q--){ scanf("%d %d",&u,&v); LCA(u,v); printf("%d\n",ans); }puts(""); } int main() { int n,m,cas=0; while(scanf("%d%d",&n,&m)==2) { if(n+m==0)break; init(); Read(m); printf("Case %d:\n",++cas); processing(); } return 0; }