【HDU2460】Network

題目鏈接:HDU2460

解法:樹鏈剖分

若原圖爲一棵樹,則所有邊都是橋。那麼先建出一棵原圖的生成樹。
對於其餘的邊 (u,v) ,在生成樹中找到 uv 的簡單路徑,並將路徑上的邊標記爲不是橋。將邊的信息轉移到點,可以樹剖實現。每次修改後查詢即可。

代碼

#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>

using namespace std;

struct edge{
    int u,v;
    edge():u(0),v(0){}
    edge(int x,int y):u(x),v(y){}
};

vector<edge> vec;
vector<int> point[100001];
int t,n,m,q,x,y,f[100001],fa[100001],son[100001],dep[100001],siz[100001],top[100001],dfn[100001],idx,tag[400001],sum[400001];
bool check[200001];

int find(int x){return f[x]==x?x:f[x]=find(f[x]);}

bool merge(int x,int y){int fx=find(x),fy=find(y);if(fx==fy)return false;return f[fx]=fy,true;}

void work(){for(int i=0;i<vec.size();++i){edge e=vec[i];int u=e.u,v=e.v;if(!merge(u,v))check[i]=true;else point[u].push_back(v),point[v].push_back(u);}}

inline void pushdown(int o,int l,int r){tag[o<<1]=tag[o<<1|1]=tag[o];int m=l+r>>1;sum[o<<1]=tag[o]*(m-l+1),sum[o<<1|1]=tag[o]*(r-m);tag[o]=0;}

void update(int o,int l,int r,int a,int b,int x){
    if(l==a&&r==b){sum[o]=(tag[o]=x)*(r-l+1);return;}
    if(tag[o])pushdown(o,l,r);
    int m=l+r>>1;if(m>=b)update(o<<1,l,m,a,b,x);else if(m<a)update(o<<1|1,m+1,r,a,b,x);else update(o<<1,l,m,a,m,x),update(o<<1|1,m+1,r,m+1,b,x);
    sum[o]=sum[o<<1]+sum[o<<1|1];
}

int query(int o,int l,int r,int a,int b){
    if(l==a&&r==b)return sum[o];
    if(tag[o])pushdown(o,l,r);
    int m=l+r>>1;if(m>=b)return query(o<<1,l,m,a,b);else if(m<a)return query(o<<1|1,m+1,r,a,b);else return query(o<<1,l,m,a,m)+query(o<<1|1,m+1,r,m+1,b);
}

void dfs1(int u){siz[u]=1;for(int v:point[u])if(v!=fa[u]){dep[v]=dep[fa[v]=u]+1,dfs1(v),siz[u]+=siz[v];if(siz[v]>siz[son[u]])son[u]=v;}}

void dfs2(int u){dfn[u]=++idx;if(son[u])top[son[u]]=top[u],dfs2(son[u]);for(int v:point[u])if(v!=fa[u]&&v!=son[u])top[v]=v,dfs2(v);}

void change(int u,int v){
    while(top[u]!=top[v]){if(dep[top[u]]>dep[top[v]])swap(u,v);update(1,1,n,dfn[top[v]],dfn[v],1),v=fa[top[v]];}
    if(dep[u]>dep[v])swap(u,v);if(dfn[u]<dfn[v])update(1,1,n,dfn[u]+1,dfn[v],1);
}

int main(){
    while(++t){
        vec.clear(),memset(fa,idx=0,sizeof(fa)),memset(dep,0,sizeof(dep)),memset(siz,0,sizeof(siz)),memset(top,0,sizeof(top)),memset(son,0,sizeof(son)),memset(dfn,0,sizeof(dfn)),memset(sum,0,sizeof(sum)),memset(tag,0,sizeof(tag)),memset(check,false,sizeof(check));
        scanf("%d%d",&n,&m);
        if(!n)return 0;for(int i=1;i<=n;++i)point[i].clear(),f[i]=i;
        for(int i=1;i<=m;++i)scanf("%d%d",&x,&y),vec.push_back(edge(x,y));
        work();
        dfs1(1),dfs2(top[1]=1);
        for(int i=0;i<vec.size();++i)if(check[i])change(vec[i].u,vec[i].v);
        scanf("%d",&q);printf("Case %d:\n",t);for(int i=1;i<=q;++i)scanf("%d%d",&x,&y),change(x,y),printf("%d\n",n-sum[1]-1);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章