Loading

【XSY2187】【HDU2460】Network

题目大意:

给你一个无向连通图,再给出一些添边操作,询问每次添边操作之后图中还剩下多少桥。


思路:

考虑求出任意一棵生成树

若连接\((u,v)\),则生成树上u到v的路径上都不是桥

设一条边的边权为这条边是不是桥,是则为1,反之则为0

用树链剖分维护每一条边权,发现只能维护点权

WDNMD

考虑化边权为点权,设点\(i\)的权值为边\((i,fa[i])\)的权值

每一次修改把两个点的LCA特判一下,不要修改就行了


#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int N=100010;
const int M=200010;

inline void read(int &x) {
    x=0;
    int f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9') {
        if (ch=='-') {
            f=-1;
        }
        ch=getchar();
    }
    while(ch>='0'&&ch<='9') {
        x=x*10+ch-'0';
        ch=getchar();
    }
    x*=f;
}

//*****MST部分*****//
struct note {
    int t;
    int next;
};

int cnt;
int head[N];
note e[M<<1];

struct edge {
    int x;
    int y;
};

int con;
edge E[M];
int f[N];
int vis[M];
int n,m,q;

inline void add(int x,int y) {
    e[++cnt].t=y;
    e[cnt].next=head[x];
    head[x]=cnt;
}

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

inline bool check(int x,int y) {
    int fx=find(x),fy=find(y);
    if (fx==fy) {
        return 0;
    } else {
        f[fx]=f[y];
        return 1;
    }
}

inline void bulid_MST() {
    for(int i=1;i<=n;i++) {
        f[i]=i;
    }
    for(int i=1;i<=m;i++) {
        if (check(E[i].x,E[i].y)) {
            con++;
            add(E[i].x,E[i].y);
            add(E[i].y,E[i].x);
            vis[i]=1;
        }
        if (con==n-1) {
            break;
        }
    }
}

//------------------------//

//*****线段树部分*****//
struct seqt {
    int ls;
    int rs;
    int val;
    int f;
    seqt() {
        ls=rs=val=0;
        f=-1;
    }
};

seqt node[N<<2];
int siz;
int rt;

inline void update(int o) {
    node[o].val=node[node[o].ls].val+node[node[o].rs].val;
}

inline void down(int o,int l,int r) {
    int mid=(l+r)>>1;
    node[node[o].ls].val=node[o].f*(mid-l+1);
    node[node[o].rs].val=node[o].f*(r-mid);
    node[node[o].ls].f=node[node[o].rs].f=node[o].f;
    node[o].f=-1;
}

void build(int &o,int l,int r) {
    o=++siz;
    node[o].f=-1;
    if (l==r) {
        node[o].val=1;
        return;
    }
    int mid=(l+r)>>1;
    build(node[o].ls,l,mid);
    build(node[o].rs,mid+1,r);
    update(o);
}

void change(int o,int l,int r,int L,int R,int val) {
    if (L<=l&&r<=R) {
        node[o].val=val*(r-l+1);
        node[o].f=val;
        return;
    }
    if (node[o].f!=-1) {
        down(o,l,r);
    }
    int mid=(l+r)>>1;
    if (L<=mid) {
        change(node[o].ls,l,mid,L,R,val);
    }
    if (mid<R) {
        change(node[o].rs,mid+1,r,L,R,val);
    }
    update(o);
}

int query(int o,int l,int r,int L,int R) {
    if (L<=l&&r<=R) {
        return node[o].val;
    }
    if (node[o].f!=-1) {
        down(o,l,r);
    }
    int mid=(l+r)>>1;
    int ans=0;
    if (L<=mid) {
        ans+=query(node[o].ls,l,mid,L,R);
    }
    if (mid<R) {
        ans+=query(node[o].rs,mid+1,r,L,R);
    }
    return ans;
}
//------------------------//

//*****树链剖分部分*****//
int tot;
int son[N],top[N],dep[N],fa[N],dfn[N],val[N];

void dfs1(int p,int fat) {
    dep[p]=dep[fat]+1;
    fa[p]=fat;
    val[p]=1;
    int max_son=-1;
    for(int i=head[p];i+1;i=e[i].next) {
        int t=e[i].t;
        if (t==fat) {
            continue;
        }
        dfs1(t,p);
        val[p]+=val[t];
        if (val[t]>max_son) {
            son[p]=t;
            max_son=val[t];
        }
    }
}

void dfs2(int p,int top_p) {
    dfn[p]=++tot;
    top[p]=top_p;
    if (!son[p]) {
        return;
    }
    dfs2(son[p],top_p);
    for(int i=head[p];i+1;i=e[i].next) {
        int t=e[i].t;
        if (t==fa[p]||t==son[p]) {
            continue;
        }
        dfs2(t,t);
    }
}

int query_tree(int x) {
    return query(rt,1,n,dfn[x],dfn[x]+val[x]-1);
}

void change_range(int x,int y,int val) {
    while(top[x]!=top[y]) {
        if (dep[top[x]]<dep[top[y]]) {
            swap(x,y);
        }
        change(rt,1,n,dfn[top[x]],dfn[x],val);
        x=fa[top[x]];
    }
    if (dep[x]>dep[y]) {
        swap(x,y);
    }
    change(rt,1,n,dfn[x]+1,dfn[y],val);
}
//------------------------/

inline void init() {
    memset(head,-1,sizeof(head));
    memset(e,0,sizeof(e));
    memset(son,0,sizeof(son));
    memset(vis,0,sizeof(vis));
    memset(node,0,sizeof(node));
    cnt=tot=siz=con=0;
}

int main() {
    int papapa=0;
    read(n),read(m);
    while(n&&m) {
        init();
        for(int i=1;i<=m;i++) {
            read(E[i].x),read(E[i].y);
        }
        bulid_MST();
        dfs1(1,1);
        dfs2(1,1);
        build(rt,1,n);
        for(int i=1;i<=m;i++) {
            if (!vis[i]) {
                change_range(E[i].x,E[i].y,0);
            }
        }
        read(q);
        printf("Case %d:\n",++papapa);
        for(int i=1;i<=q;i++) {
            int x,y;
            read(x),read(y);
            change_range(x,y,0);
            printf("%d\n",query_tree(1)-1);
        }
        printf("\n");
        read(n),read(m);
    }
    return 0;
}

posted @ 2019-10-11 21:34  tt66ea蒟蒻  阅读(236)  评论(0编辑  收藏  举报