• BZOJ_2443_[Usaco2011 Open]奇数度数 _并查集+树形DP


    BZOJ_2443_[Usaco2011 Open]奇数度数 _并查集、

    Description

    奶牛们遭到了进攻!在他们的共和国里,有N(1 <= N <=50,000)个城市,由M(1 <= M <= 100,000)条无向的道路连
    接城市A_i和B_i(1 <= A_i <= N;1 <= B_i <= N;A_i != B_i; 不会有重复的道路出现)。然而,整个共和国不一定
    是连通的——有一些城市无法到达另外一些城市。入侵者想得到共和国的地图。(入侵者很傻,因此,他们的绘制
    地图的方法是去访问每一条边,T_T)。奶牛想要折磨一下入侵者,使得他们尽可能难地完成地图绘制。因此,奶牛
    会破坏若干条道路。请你帮助奶牛找到一个道路的子集,使得每条边每个点的度数为奇数。或者输出不存在这样的
    一个子集。(奶牛的图论学得真好.= =||)举个例子,考虑下面的共和国:
    1---2
    /
      3---4
    如果我们保留道路1-3,2-3和3-4,破坏道路1-2,那么城市1,2,4都只有一条边相连,城市3有3条边相连:
    1   2
    /
      3---4

    Input

    * 第一行:两个用空格隔开的整数:N和M
    * 第二行到M+1行:第i+1行有两个空格隔开的整数A_i和

    Output

    * 第一行: 一个整数表示需要保留的道路数量
    * 第二到K+1行:每行一个数表示保留的道路的编号,范围是1...M。

    Sample Input

    4 4
    1 2
    2 3
    3 1
    3 4

    Sample Output

    3
    2
    3
    4

    直接说结论:任意拽出一棵生成树,把非树边扔掉,再在树的内部树形DP判断是否有解。
    证明一下:对于一条非树边<u,v>,如果可能的构造法包含它,我们可以让<u,v>路径上所有边更改选择状态从而不选这条边,路径上的点的奇偶性不变。
    然后并查集维护一下即可。
     
    代码:
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define N 50050
    #define M 100050
    using namespace std;
    inline char nc() {
        static char buf[100000],*p1,*p2;
        return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
    }
    int rd() {
        int x=0; char s=nc();
        while(s<'0'||s>'9') s=nc();
        while(s>='0'&&s<='9') x=(x<<3)+(x<<1)+s-'0',s=nc();
        return x;
    }
    char pbuf[100000],*pp=pbuf;
    void push(const char c) {
        if(pp-pbuf==100000) fwrite(pbuf,1,100000,stdout),pp=pbuf;
        *pp++=c;
    }
    void write(int x) {
        static int sta[35];
        int top=0;
        do{sta[top++]=x%10,x/=10;}while(x);
        while(top) push(sta[--top]+'0');
    }
    int head[N],to[N<<1],nxt[N<<1],val[N<<1],cnt;
    int is[M],tot,n,m,fa[N],f[N],vis[N];
    int find(int x) {return fa[x]==x?x:fa[x]=find(fa[x]);}
    void add(int u,int v,int w) {
        to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt; val[cnt]=w;
    }
    void dfs(int x,int y) {
        int i,now=0; vis[x]=1;
        for(i=head[x];i;i=nxt[i]) {
            if(to[i]!=y) {
                dfs(to[i],x);
                if(f[to[i]]) now++;
                else is[val[i]]=1,tot--;
            }
        }
        f[x]=!(now&1);
    }
    int main() {
        n=rd(); m=rd(); tot=m;
        register int i,x,y;
        for(i=1;i<=n;i++) fa[i]=i;
        for(i=1;i<=m;i++) {
            x=rd(); y=rd();
            int dx=find(x),dy=find(y);
            if(dx!=dy) add(x,y,i),add(y,x,i),fa[dx]=dy;
            else is[i]=1,tot--;
        }
        for(i=1;i<=n;i++) {
            if(!vis[i]) {
                dfs(i,0); if(f[i]) {puts("-1"); return 0;}
            }
        }
        write(tot); push('
    ');
        for(i=1;i<=m;i++) if(!is[i]) write(i),push('
    ');
        fwrite(pbuf,1,pp-pbuf,stdout);
    }
    
  • 相关阅读:
    网站安全处理记录
    C#图片截取(1.按照百分比压缩,2.制定大小压缩)、压缩
    reportviewer导出格式控制
    NPOI 读写excel
    asp.net防止刷新时重复提交
    VS Code MySql扩展 最后完全免费版本 4.5.12
    jmeter中HTTP Cookie Manager
    切换webview报错Failed to start Chromedriver session: Failed to get sockets matching: @weblayer_devtools_remote_.*4738
    在指定目录下面带环境变量运行jmeter
    fidder打断点
  • 原文地址:https://www.cnblogs.com/suika/p/9219573.html
Copyright © 2020-2023  润新知