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)

View Code
#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;
}

posted on 2012-07-06 15:27  aigoruan  阅读(297)  评论(0)    收藏  举报

导航