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
1 2
2 3
3 1
3 4
Sample Output
3
2
3
4
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); }