zoukankan      html  css  js  c++  java
  • CF19 E Fairy——树上差分

    题目:http://codeforces.com/contest/19/problem/E

    先把图连成一棵树,然后对于每条非树边,判断它是在奇环中还是偶环中;

    把环上的点打上相应的差分标记,并记录有多少个奇环;

    dfs 出来后判断,若没有奇环,那么所有边都可以删;

    若有奇环 k 个,遍历边,在 k 个奇环中而不在偶环中的边可以删;

    如果一条边既在奇环中又在偶环中,那么若删掉它,原来的一奇环一偶环会合并成一个大奇环,所以这种边不能删;

    写、调了整整两小时,改了许多冗余的地方和错误的地方才终于A了,我这代码能力...

    码力++!

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int const maxn=2e4+5;
    int n,m,fa[maxn],sf[maxn],sg[maxn],g[maxn],f[maxn],ans[maxn],ns;
    int col[maxn],hd[maxn],ct,cnt,qhd[maxn],numj;
    bool vis[maxn];
    struct N{
        int to,nxt,edge;
        N(int t=0,int n=0,int e=0):to(t),nxt(n),edge(e) {}
    }ed[maxn<<1],q[maxn];
    struct T{
        int ff,gg;
        T(int f=0,int g=0):ff(f),gg(g) {}
    };
    inline int rd()
    {
        int ret=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
        while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar();
        return ret*f;
    }
    inline int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
    inline void add(int x,int y,int e){ed[++ct]=N(y,hd[x],e); hd[x]=ct;}
    inline void ad(int x,int y,int e){q[++cnt]=N(y,qhd[x],e); qhd[x]=cnt;}
    inline void dfs2(int x,int pre)
    {
        vis[x]=1; col[x]=!col[pre];
        for(register int i=qhd[x];i;i=q[i].nxt)
        {
            int u=q[i].to;
            if(!vis[u])continue;
            int lca=find(u);
            if(col[u]==col[x])
            {
    //            f[u]++,f[i]++,f[pr[lca]]-=2,numj++;
                f[u]++,f[x]++,f[lca]-=2,numj++;
                sf[q[i].edge]=1; 
            }
            else 
            {
    //            g[u]++,g[i]++,g[pr[lca]]-=2,numo++;
                g[u]++,g[x]++,g[lca]-=2;
            }
        }
        for(register int i=hd[x],u;i;i=ed[i].nxt)
            if((u=ed[i].to)!=pre)dfs2(u,x);
        fa[x]=pre;
    }
    inline T dfs3(int x,int pre)
    {
        int smf=f[x],smg=g[x]; vis[x]=1;//smf,smg!=0!!!
        for(register int i=hd[x],u;i;i=ed[i].nxt)
        {
            if((u=ed[i].to)==pre)continue;
            T k=dfs3(u,x);int e=ed[i].edge;
            sf[e]=k.ff; sg[e]=k.gg;
            smf+=k.ff; smg+=k.gg;
        }
        return T(smf,smg);
    }
    int main()
    {
        n=rd(); m=rd();
        for(register int i=1;i<=n;i++)fa[i]=i;
        for(register int i=1,u,v;i<=m;i++)
        {
            u=rd(); v=rd();
            if(find(u)!=find(v))
            {
                fa[find(u)]=find(v);
                add(u,v,i); add(v,u,i);
            }
            else ad(u,v,i),ad(v,u,i);
        }
        for(register int i=1;i<=n;i++)fa[i]=i;
        for(int i=1;i<=n;i++)if(!vis[i])dfs2(i,0);//不仅dfs(1,0) 
        memset(vis,0,sizeof vis);
        if(!numj)
        {
            printf("%d
    ",m);
            for(int i=1;i<=m;i++)printf("%d ",i);
            return 0;
        }
        for(int i=1;i<=n;i++)if(!vis[i])dfs3(i,0);
        memset(vis,0,sizeof vis);
        for(register int i=1;i<=m;i++)
            if(sf[i]==numj&&!sg[i])ans[++ns]=i;
        printf("%d
    ",ns);
        sort(ans+1,ans+ns+1);
        for(register int i=1;i<=ns;i++)printf("%d ",ans[i]);
        return 0;
    }
  • 相关阅读:
    Android开发
    Android随笔
    Android开发
    宁波大学NBU计算机大三下册期末考试
    2021浙江省大学生程序设计竞赛D题 Shortest Path Query(最短路+思维)
    NWERC 2020A Atomic Energy(背包+思维)
    CF1454E Number of Simple Paths(容斥+基环树)
    CF549F(分治+启发式合并)
    HDU5293 Tree chain problem (LCA+树链剖分+线段树)
    HDU156 The more, The Better(dp+背包)
  • 原文地址:https://www.cnblogs.com/Zinn/p/9278315.html
Copyright © 2011-2022 走看看