HDU 5458 Stability

44 篇文章 0 订阅
6 篇文章 0 订阅

HDU 5458 Stability

树链剖分,巨麻烦

题意

给一个图,可能有重边与自环。有一些操作:删去某条边,保证边一定存在;查询两点之间的桥数。保证任意时刻图至少是一棵树。

思路

老谭看一眼觉得是缩点,可能还要剖分,就丢给我。我敲完水题就开始了。。爆炸。。。

思路很清晰,两点之间的双联通分量一定对答案没有贡献,剩下的一条路贡献1。又最后保证联通,至少是树,所以思路很明显(有个NOI题,棘手的操作),先得到最后的图,倒着操作。

先读进图用map存,按操作删边,得到最后的图,建出链式前向星,跑一遍双联通分量缩点,这里我选择了重新建图,带着原图跑太容易写错了。对新图跑树链剖分,建线段树,每条路记成1。然后倒着操作来,加边[a,b]意味着有了新的双联通分量,相当于将[a,b]路径上的边权置为0。

竟然T了???我完美的Ologn的算法啊???调了两天,至今不知道为什么会T。。

看网上有说用并查集代替双联通缩点的,这样就是得到最后的图建链式前向星时,用并查集维护,如果两点已经联通,那么先不处理,把这个pair存起来。这样建出来的一定是树,跑树链剖分。在把刚才存起来的pair们的路径上的边置0,因为这些路相当于形成了双联通分量。然后过了。。。

我觉得缩点的复杂度要低很多啊,因为剖分时点就少了。。网上也有缩点过的%%%。并不知道我哪写丑了。

代码

AC

#include<bits\stdc++.h>
#define M(a,b) memset(a,b,sizeof(a))
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
using namespace std;
const int MAXN=30007;
const int MAXM=100007;

//OP
struct OP
{
    int op, a, b;
}op[MAXM];
multiset<pair<int, int> >se;
multiset<pair<int, int> >sse;

//dsu
int fa[MAXN];
int getfa(int x)
{
    return x==fa[x] ? x : fa[x]=getfa(fa[x]);
}

//Edge
struct Edge
{
    int to, ne;
}e[MAXM<<2];
int head[MAXN], edgenum;
void addedge(int u, int v)
{
    e[edgenum].to=v, e[edgenum].ne=head[u], head[u]=edgenum++;
    e[edgenum].to=u, e[edgenum].ne=head[v], head[v]=edgenum++;
}

//
int Hson[MAXN], SonAmount[MAXN], Father[MAXN], Depth[MAXN];
int Dfsnum[MAXN], TopOfHeavyChain[MAXN];
int dfscount;

void dfs1(int n)
{
    SonAmount[n]=1;
    for(int i=head[n];~i;i=e[i].ne)
    {
        int to=e[i].to;
        if(to==Father[n]/*||Depth[to]*/) continue;
        Depth[to]=Depth[n]+1;

        Father[to]=n;
        dfs1(to);
        SonAmount[n]+=SonAmount[to];
        if(SonAmount[to]>SonAmount[Hson[n]]) Hson[n]=to;
    }
    return;
}
void dfs2(int n, int prev)
{
    Dfsnum[n]=++dfscount;
    TopOfHeavyChain[n]=prev;
    if(!Hson[n]) return;
    dfs2(Hson[n], prev);
    for(int i=head[n];~i;i=e[i].ne)
    {
        int to=e[i].to;
        if(to==Hson[n]||to==Father[n]) continue;
        dfs2(to, to);
    }
}

struct Stree
{
    int num, lazy;
}stree[MAXN<<2];
inline void pushup(int rt)
{
    stree[rt].num=stree[rt<<1].num+stree[rt<<1|1].num;
}
void build(int l, int r, int rt)
{
    stree[rt].lazy=0;
    if(l==r)
    {
        stree[rt].num=1;
        return;
    }
    int mid=(l+r)>>1;
    build(lson), build(rson);
    pushup(rt);
}
void update(int L, int R, int l, int r, int rt)
{
    if(stree[rt].lazy) return;
    if(L<=l&&r<=R)
    {
        stree[rt].lazy=1;
        stree[rt].num=0;
        return;
    }
    int mid=(l+r)>>1;
    if(L<=mid) update(L, R, lson);
    if(mid<R) update(L, R, rson);
    pushup(rt);
}
int query(int L, int R, int l, int r, int rt)
{
    if(stree[rt].lazy) return 0;
    if(L<=l&&r<=R) return stree[rt].num;
    int mid=(l+r)>>1;
    int res=0;
    if(L<=mid) res+=query(L, R, lson);
    if(mid<R) res+=query(L, R, rson);
    return res;
}
void solveup(int n, int l, int r)
{
    int fl=TopOfHeavyChain[l], fr=TopOfHeavyChain[r];
    while(fl!=fr)
    {
        if(Depth[fl]>Depth[fr])
        {
            update(Dfsnum[fl], Dfsnum[l], 1, n, 1);
            l=Father[fl];fl=TopOfHeavyChain[l];
        }
        else
        {
            update(Dfsnum[fr], Dfsnum[r], 1, n, 1);
            r=Father[fr];fr=TopOfHeavyChain[r];
        }
    }
    if(l==r) return;
    if(Depth[l]>Depth[r])
        update(Dfsnum[Hson[r]], Dfsnum[l], 1, n, 1);
    else update(Dfsnum[Hson[l]], Dfsnum[r], 1, n, 1);
}
int solvequ(int n, int l, int r)
{
    int fl=TopOfHeavyChain[l], fr=TopOfHeavyChain[r];
    int res=0;
    while(fl!=fr)
    {
        if(Depth[fl]>Depth[fr])
        {
            res+=query(Dfsnum[fl], Dfsnum[l], 1, n, 1);
            l=Father[fl];
            fl=TopOfHeavyChain[l];
        }
        else
        {

            res+=query(Dfsnum[fr], Dfsnum[r], 1, n, 1);
            r=Father[fr];
            fr=TopOfHeavyChain[r];
        }
    }
    if(l!=r)
    {
        if(Depth[l]>Depth[r])
        {
            res+=query(Dfsnum[Hson[r]], Dfsnum[l], 1, n, 1);
        }
        else
        {
            res+=query(Dfsnum[Hson[l]], Dfsnum[r], 1, n, 1);
        }
    }
    return res;
}

void init(int n, int m)
{
    se.clear();sse.clear();
    for(int i=0;i<=n;i++) fa[i]=i;
    M(head, -1);edgenum=0;

    M(stree, 0);

    M(Hson, 0);M(Depth, 0);
    dfscount=0;Father[1]=1;Depth[1]=1;
}
int res[MAXM], rcnt;
int main()
{
    int T;scanf("%d", &T);int cas=0;
    while(T--)
    {
        int n, m, q;scanf("%d%d%d", &n, &m, &q);
        init(n, m);
        for(int i=1;i<=m;i++)
        {
            int a, b;scanf("%d%d", &a, &b);
            if(a>b) swap(a, b);
            se.insert(make_pair(a, b));
        }
        for(int i=1;i<=q;i++)
        {
            int o, a, b;scanf("%d%d%d", &o, &a, &b);
            if(a>b) swap(a, b);
            op[i].op=o, op[i].a=a, op[i].b=b;
            if(o==1)
            {
                multiset<pair<int, int>>::iterator ite=se.find(make_pair(a, b));
                se.erase(ite);
            }
        }
        for(multiset<pair<int, int>>::iterator ite=se.begin();ite!=se.end();ite++)
        {
            int a=ite->first, b=ite->second;
            int aa=getfa(a), bb=getfa(b);
            if(aa!=bb)
            {
                fa[aa]=bb;
                addedge(a, b);
            }
            else sse.insert(make_pair(a, b));
        }
        dfs1(1);dfs2(1, 1);build(1, n, 1);
        for(multiset<pair<int, int>>::iterator ite=sse.begin();ite!=sse.end();ite++)
        {
            int a=ite->first, b=ite->second;
            solveup(n, a, b);
        }
        rcnt=0;
        for(int i=q;i>0;i--)
        {
            if(op[i].op==1)
            {
                solveup(n, op[i].a, op[i].b);
            }
            else
            {
                res[++rcnt]=(solvequ(n, op[i].a, op[i].b));
            }
        }
        printf("Case #%d:\n", ++cas);
        for(int i=rcnt;i>0;i--)
            printf("%d\n", res[i]);
    }
    return 0;
}

缩点TLE

#include<bits\stdc++.h>
#define M(a,b) memset(a,b,sizeof(a))
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
using namespace std;
const int MAXN=30007;
const int MAXM=100007;
typedef long long LL;

//Operator
struct OP
{
    int op;
    int a, b;
    int res;
    OP() { op=a=b=0; }
    void read() { scanf("%d%d%d", &op, &a, &b); }
}op[MAXM];

//Edge,Targan
struct Edge
{
    int to, ne;
    int fl;
}e[MAXM<<2];
int head[MAXN], edgenum;
vector<int> G[MAXN];
void addedge(int u, int v)
{
    e[edgenum].to=v, e[edgenum].ne=head[u], e[edgenum].fl=0, head[u]=edgenum++;
    e[edgenum].to=u, e[edgenum].ne=head[v], e[edgenum].fl=0, head[v]=edgenum++;
}
struct Targan
{
    int pre[MAXN], lowlink[MAXN], sccno[MAXN], dfs_clock, scc_cnt;
    stack<int> S;
    void init()
    {
        while(!S.empty()) S.pop();
    }
    void dfs(int u, int fa)
    {
        pre[u]=lowlink[u]=++dfs_clock;
        S.push(u);
        for(int i=head[u];~i;i=e[i].ne)
        {
            int v=e[i].to;
            if(v==fa||e[i].fl) continue;
            if(!pre[v])
            {
                dfs(v, u);
                lowlink[u]=min(lowlink[u], lowlink[v]);
            }
            else
            {
                lowlink[u]=min(lowlink[u], pre[v]);
            }
        }
        if(lowlink[u]==pre[u])
        {
            scc_cnt++;
            while(1)
            {
                int x=S.top();S.pop();
                sccno[x]=scc_cnt;
                if(x==u) break;
            }
        }
    }
    void find_scc(int n)
    {
        dfs_clock=scc_cnt=0;
        M(sccno, 0);M(pre, 0);M(lowlink, 0);
        for(int i=1;i<=n;i++)
        {
            if(!pre[i]) dfs(i, -1);
        }
    }
}targan;

int Hson[MAXN], SonAmount[MAXN], Father[MAXN], Depth[MAXN];
int Dfsnum[MAXN], TopOfHeavyChain[MAXN];
int dfscount;
void dfs1(int n)
{
    SonAmount[n]=1;
    for(int i=0;i<G[n].size();i++)
    {
        int to=G[n][i];
        if(to==Father[n]) continue;
        Depth[to]=Depth[n]+1;

        Father[to]=n;
        dfs1(to);
        SonAmount[n]+=SonAmount[to];
        if(SonAmount[to]>SonAmount[Hson[n]]) Hson[n]=to;
    }
    return;
}
void dfs2(int n, int prev)
{
    Dfsnum[n]=++dfscount;
    TopOfHeavyChain[n]=prev;
    if(!Hson[n]) return;
    dfs2(Hson[n], prev);
    for(int i=0;i<G[n].size();i++)
    {
        int to=G[n][i];
        if(to==Hson[n]||to==Father[n]) continue;
        dfs2(to, to);
    }
}

struct Stree
{
    int lazy;int num;
    Stree() { lazy=0;num=0; }
}stree[MAXN<<2];
inline void pushup(int rt)
{
    stree[rt].num=stree[rt<<1].num+stree[rt<<1|1].num;
}
void build(int l, int r, int rt)
{
    stree[rt].lazy=0;
    if(l==r) { stree[rt].num=1;return; }
    int mid=(l+r)>>1;
    build(lson), build(rson);
    pushup(rt);
}
void update(int L, int R, int l, int r, int rt)
{
    if(stree[rt].lazy) return;
    if(L<=l&&r<=R)
    {
        stree[rt].lazy=1;
        stree[rt].num=0;
        return;
    }
    int mid=(l+r)>>1;
    if(L<=mid) update(L, R, lson);
    if(mid<R) update(L, R, rson);
    pushup(rt);
}
int query(int L, int R, int l, int r, int rt)
{
    if(stree[rt].lazy) return 0;
    if(L<=l&&r<=R) return stree[rt].num;
    int mid=(l+r)>>1;
    int res=0;
    if(L<=mid) res+=query(L, R, lson);
    if(mid<R) res+=query(L, R, rson);
    return res;
}

void solveup(int n, int l, int r)
{
    int fl=TopOfHeavyChain[l], fr=TopOfHeavyChain[r];
    while(fl!=fr)
    {
        if(Depth[fl]>Depth[fr])
        {
            update(Dfsnum[fl], Dfsnum[l], 1, n, 1);
            l=Father[fl];fl=TopOfHeavyChain[l];
        }
        else
        {
            update(Dfsnum[fr], Dfsnum[r], 1, n, 1);
            r=Father[fr];fr=TopOfHeavyChain[r];
        }
    }
    if(l==r) return;
    if(Depth[l]>Depth[r])
        update(Dfsnum[Hson[r]], Dfsnum[l], 1, n, 1);
    else update(Dfsnum[Hson[l]], Dfsnum[r], 1, n, 1);
}
int solvequ(int n, int l, int r)
{
    int fl=TopOfHeavyChain[l], fr=TopOfHeavyChain[r];
    int res=0;
    while(fl!=fr)
    {
        if(Depth[fl]>Depth[fr])
        {
            res+=query(Dfsnum[fl], Dfsnum[l], 1, n, 1);
            l=Father[fl];
            fl=TopOfHeavyChain[l];
        }
        else
        {

            res+=query(Dfsnum[fr], Dfsnum[r], 1, n, 1);
            r=Father[fr];
            fr=TopOfHeavyChain[r];
        }
    }
    if(l!=r)
    {
        if(Depth[l]>Depth[r])
        {
            res+=query(Dfsnum[Hson[r]], Dfsnum[l], 1, n, 1);
        }
        else
        {
            res+=query(Dfsnum[Hson[l]], Dfsnum[r], 1, n, 1);
        }
    }
    return res;
}

int main()
{
    int T;scanf("%d", &T);int cas=0;
    while(T--)
    {
        printf("Case #%d:\n", ++cas);
        M(head, -1);edgenum=0;
        int n, m, q;scanf("%d%d%d", &n, &m, &q);
        for(int i=1;i<=m;i++)
        {
            int u, v;scanf("%d%d", &u, &v);
            addedge(u, v);
        }
        for(int i=1;i<=q;i++)
        {
            int o, a, b;scanf("%d%d%d", &o, &a, &b);
            if(a>b) swap(a, b);
            op[i].op=o, op[i].a=a, op[i].b=b;
            if(o==1)
            {
                for(int j=head[a];~j;j=e[j].ne)
                {
                    if(e[j].to==b)
                    {
                        e[j].fl=1, e[j^1].fl=1;
                        break;
                    }
                }
            }
        }
        targan.init();
        targan.find_scc(n);

        for(int i=1;i<=n;i++) G[i].clear();
        for(int i=1;i<=n;i++)
        {
            int u=0, v=0;u=targan.sccno[i];
            for(int j=head[i];~j;j=e[j].ne)
            {
                if(e[j].fl) continue;
                v=targan.sccno[e[j].to];
                if(u>targan.scc_cnt||v>targan.scc_cnt) assert("dsf");
                G[u].push_back(v);
                G[v].push_back(u);
            }
        }

        n=targan.scc_cnt;
        for(int i=1;i<=n;i++)
        {
            sort(G[i].begin(), G[i].end());
            G[i].erase(unique(G[i].begin(), G[i].end()), G[i].end());
        }

        M(Hson, 0);M(Depth, 0);
        Father[1]=1;Depth[1]=1;dfscount=0;
        dfs1(1), dfs2(1, 1);build(1, n, 1);

        for(int i=q;i>0;i--)
        {
            if(op[i].op==1)
            {
                solveup(n, targan.sccno[op[i].a], targan.sccno[op[i].b]);
            }
            else
            {
                op[i].res=solvequ(n, targan.sccno[op[i].a], targan.sccno[op[i].b]);
            }
        }
        for(int i=1;i<=q;i++)
        {
            if(op[i].op==2) printf("%d\n", op[i].res);
        }
    }
    //system("pause");
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值