• CF 19E Fairy——树上差分


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

    去掉一条边,使无向图变成二分图。

    该边应该被所有奇环经过,且不被偶环经过。

      因为一条非树边一定只在一个环里。所以一条既被所有奇环经过又被偶环经过的边是树边。如果把它去掉,将无法处理包含它的那个偶环的非树边和包含它的某个奇环的非树边加上两段树边所构成的奇环。

    找这样的边,弄一个边上的树上差分就行了。

    可以模仿kruscal用并查集弄一个生成树。不过dfs其实也行。

    注意图可能不连通。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N=1e4+5;
    int n,m,c[N][2],fa[N],head[N],t[N<<1],next[N<<1],tot;
    int hd[N],xnt,col[N],cnt,pa[N],prbh,bh[N<<1],q[N],qnt;
    bool vis[N];
    struct Ed{
      int nxt,to,bh;Ed(int n=0,int t=0,int b=0):nxt(n),to(t),bh(b) {}
    }ed[N<<1];
    int find(int a){return fa[a]==a?a:fa[a]=find(fa[a]);}
    void add(int x,int y,int b)
    {
      ed[++xnt]=Ed(hd[x],y,b);hd[x]=xnt;
      ed[++xnt]=Ed(hd[y],x,b);hd[y]=xnt;
    }
    void dfs(int cr,int f)
    {
      vis[cr]=1;
      for(int i=head[cr],v;i;i=next[i])
        if(col[v=t[i]])
          {
        int f0=find(v),d=(col[cr]==col[v]);
        if(d){cnt++;if(cnt==1)prbh=bh[i];}
        c[cr][d]++;c[v][d]++;c[f0][d]-=2;
          }
      for(int i=hd[cr];i;i=ed[i].nxt)
        if(ed[i].to!=f)
          {
        col[ed[i].to]=3-col[cr];dfs(ed[i].to,cr);
          }
      fa[cr]=f;
    }
    void dfsx(int cr,int f,int eb)
    {
      vis[cr]=1;
      for(int i=hd[cr],v;i;i=ed[i].nxt)
        if((v=ed[i].to)!=f)
          {
        dfsx(v,cr,ed[i].bh);
        c[cr][0]+=c[v][0];c[cr][1]+=c[v][1];
          }
      if(c[cr][1]==cnt&&!c[cr][0])q[++qnt]=eb;
    }
    int main()
    {
      scanf("%d%d",&n,&m);int x,y;
      for(int i=1;i<=n;i++)fa[i]=i;
      for(int i=1;i<=m;i++)
        {
          scanf("%d%d",&x,&y);
          if(find(x)!=find(y))
        {
          add(x,y,i);
          fa[find(x)]=find(y);
        }
          else{
        t[++tot]=y;next[tot]=head[x];head[x]=tot;bh[tot]=i;
        t[++tot]=x;next[tot]=head[y];head[y]=tot;bh[tot]=i;
          }
        }
      for(int i=1;i<=n;i++)fa[i]=i;
      for(int i=1;i<=n;i++) if(!vis[i])
          col[i]=1,dfs(i,0);
      if(!cnt)
        {
          printf("%d
    ",m);
          for(int i=1;i<=m;i++)printf("%d ",i);return 0;
        }
      if(cnt==1)q[++qnt]=prbh;
      memset(vis,0,sizeof vis);
      for(int i=1;i<=n;i++) if(!vis[i])dfsx(i,0,0);
      sort(q+1,q+qnt+1);
      printf("%d
    ",qnt);
      for(int i=1;i<=qnt;i++)printf("%d ",q[i]);
      return 0;
    }
  • 相关阅读:
    eclipse的优化 gc.log
    一次使用Eclipse Memory Analyzer分析Tomcat内存溢出
    JVM系列三:JVM参数设置、分析
    热加载
    彻底理解JAVA动态代理
    Linux下查看Web服务器当前的并发连接数和TCP连接状态
    个人博客 V0.0.3 版本 ...
    HTML5本地存储——IndexedDB(一:基本使用)
    如何在Blog中加入Google Analytics
    webpack中实现按需加载
  • 原文地址:https://www.cnblogs.com/Narh/p/9278306.html
Copyright © 2020-2023  润新知