zoukankan      html  css  js  c++  java
  • Codeforces 19E 树上差分

    思路:

    先随便建出来一棵搜索树(图可能不连通?)

    每一条非树边(剩下的边)和树边都可以构成一个环。 

    我们只看一个非树边和某些树边构成的这些环。

    分成三种情况:

    1.没有奇环  所有边都可以删

    2.有一个奇环  奇环上的边可以删

    3.有一堆奇环,一堆偶环

    边化到点上

    如果是奇环 非树边为(x,y) 在树上x,y这两个地方+1 lca(x,y)-2

    偶环相反

    做一遍树上递推上去

    最后如果答案和奇环边的数量相等  这个边可以删。

    //By SiriusRen
    #include <bits/stdc++.h>
    using namespace std;
    const int N=20050;
    int n,m,xx,yy,v[N],next[N],first[N],tot,num,T,stk[N],a[N],odd,R[N],remm,lastT,
        rev[N],fa[N],vis[N],size[N],son[N],dfn[N],cnt,top[N],deep[N],ans,ra[N];
    struct Node{int x,y,wei;}rec[N];
    void add(int x,int y){v[tot]=y,next[tot]=first[x],first[x]=tot++;}
    void dfs1(int x){
        size[x]=1,vis[x]=1,rev[++T]=x,stk[T]=x;
        for(int i=first[x];~i;i=next[i])if(v[i]!=fa[x]){
            if(vis[v[i]]){rec[++num].x=x,rec[num].y=v[i],rec[num].wei=i/2+1;continue;}
            R[v[i]]=i/2+1,deep[v[i]]=deep[x]+1,fa[v[i]]=x;
            dfs1(v[i]),size[x]+=size[v[i]];
            if(size[v[i]]>size[son[x]])son[x]=v[i];
        }
    }
    void dfs2(int x,int tp){
        vis[x]=1,dfn[x]=++cnt;top[x]=tp;
        if(son[x])dfs2(son[x],tp);
        for(int i=first[x];~i;i=next[i])if(v[i]!=fa[x]&&v[i]!=son[x]&&!vis[v[i]])dfs2(v[i],v[i]);
    }
    int lca(int x,int y){
        int fx=top[x],fy=top[y];
        while(fx!=fy){
            if(deep[fx]<deep[fy])swap(fx,fy),swap(x,y);
            x=fa[fx],fx=top[x];
        }if(deep[x]<deep[y])return x;return y;
    }
    int main(){
        memset(first,-1,sizeof(first));
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)scanf("%d%d",&xx,&yy),add(xx,yy),add(yy,xx);
        for(int i=1;i<=n;i++)if(!vis[i]){
            dfs1(i);for(int j=lastT;j<=T;j++)vis[rev[j]]=0;dfs2(i,i);lastT=T;
        }for(int i=1;i<=num;i++){
            if((deep[rec[i].x]%2)==(deep[rec[i].y]%2))
                a[rec[i].x]++,a[rec[i].y]++,a[lca(rec[i].x,rec[i].y)]-=2,odd++,remm=rec[i].wei;
            else a[rec[i].x]--,a[rec[i].y]--,a[lca(rec[i].x,rec[i].y)]+=2;
        }if(!odd){printf("%d
    ",m);for(int i=1;i<=m;i++)printf("%d ",i);return 0;}
        for(int i=n;i;i--)a[fa[stk[i]]]+=a[stk[i]];
        for(int i=1;i<=n;i++)if(a[i]==odd)ra[++ans]=R[i];
        if(odd==2)ra[++ans]=remm;
        printf("%d
    ",ans),sort(ra+1,ra+1+ans);
        for(int i=1;i<=ans;i++)printf("%d ",ra[i]);
    }
  • 相关阅读:
    HTTP深入浅出 http请求
    ASP.NET MVC 4
    ASP.NET MVC 4 (十三) 基于表单的身份验证
    ASP.NET MVC 4 (十二) Web API
    ASP.NET MVC 4 (十一) Bundles和显示模式
    ASP.NET MVC 4 (十) 模型验证
    ASP.NET MVC 4 (九) 模型绑定
    ASP.NET MVC 4 (八) URL链接和Ajax帮助函数
    ASP.NET MVC 4 (七) 模板帮助函数
    ASP.NET MVC 4 (六) 帮助函数
  • 原文地址:https://www.cnblogs.com/SiriusRen/p/9281683.html
Copyright © 2011-2022 走看看