codevs 3298 幸福的烦恼
2015-03-11 08:52
190 查看
题目描述 Description
GFS准备了一场丰厚的晚宴来宴请他的MM们,共有n个MM要来参加这场宴会,GFS为她们准备了m种菜品。但并不是每个 MM都喜欢所有的菜,每个MM都有自己喜欢吃菜品,而如果餐桌上相邻两个MM有共同喜欢的菜,她们就会互相争抢。为了维护世界的和谐,聪明的 GFS必须合理安排好他的MM们的座次。每张餐桌都是圆形的,GFS拥有足够多的桌子来安排他的 MM,但是为了防止MM们产生孤单的感觉,不允许有MM单桌的情形,也就是说每张桌子至少有两个MM。当然了,每个MM都不能与旁边的两个MM有共同喜欢吃的菜。
问是否存在这样的安排方案使得每个MM都能满意。
输入描述 Input Description
第一行一个正整数T,表示数据组数。
对于每个测试数据,第一行为两个正整数n和m。
接下来n行,每行第一个数k,表示这个MM有k个喜欢的菜品,之后k个数为MM喜欢的菜品的编号。菜品编号为1到m。
输出描述 Output Description
共包含T行,每行“Yes”或“No”。“Yes”表示存在一种方案,“No”表示不存在。
样例输入 Sample Input
2
3 4
2 2 4
1 3
1 2
5 4
2 1 3
2 2 4
1 2
1 3
1 4
样例输出 Sample Output
No
Yes
数据范围及提示 Data Size & Hint
对于30%的数据:N ≤ 16。
另有30%的数据:M ≤ 2。
对于100%的数据:1 ≤ T ≤ 10,1 ≤ N ≤ 500,1 ≤ M ≤ 30。
这题算是按照自己的思路写出来的。。。
首先,贾大神可贵地指出:任何大于等于四个人的桌子都可以拆成两个人的桌子。。这指引我们考虑两两配对。。(事实上我的这个方法在存在只能某几个三人组坐一起时应该是不对的。。)
将可以相邻的人连无向边
对于n是偶数,我们判断一下这个图的最小路径覆盖是否为边数除以二,如果是,那么我们就有使最小路径覆盖的边的端点的人两两一桌的方案了。n如果是奇数,枚举拆一个点,看剩下偶数个点是否满足刚才条件,再看最后拆的点能否和某人有边,如果有,就是yes
这样把数组开够之后,3个WA,一个T
鞠大神搞到AC代码之后,我们通过对拍发现,单独的点要想和某两人做一桌,必须和两人都可!!而不是一人!!!在匹配时记录这个点和哪个点匹配。。再判断。。
1个WA,1个T
我们终于发现匹配时得到的错误匹配要及时复原为0。。这样就不WA了。。。至于T的点,m=2,构成二分图,大概是可连的边太多。。所以直接判断两边的结点数一不一样。
我的这个方法好像和那个AC代码有很大偏差。。它不仅代码短,而且快,空间也少。。。。
总之我的脑残与日俱增。
GFS准备了一场丰厚的晚宴来宴请他的MM们,共有n个MM要来参加这场宴会,GFS为她们准备了m种菜品。但并不是每个 MM都喜欢所有的菜,每个MM都有自己喜欢吃菜品,而如果餐桌上相邻两个MM有共同喜欢的菜,她们就会互相争抢。为了维护世界的和谐,聪明的 GFS必须合理安排好他的MM们的座次。每张餐桌都是圆形的,GFS拥有足够多的桌子来安排他的 MM,但是为了防止MM们产生孤单的感觉,不允许有MM单桌的情形,也就是说每张桌子至少有两个MM。当然了,每个MM都不能与旁边的两个MM有共同喜欢吃的菜。
问是否存在这样的安排方案使得每个MM都能满意。
输入描述 Input Description
第一行一个正整数T,表示数据组数。
对于每个测试数据,第一行为两个正整数n和m。
接下来n行,每行第一个数k,表示这个MM有k个喜欢的菜品,之后k个数为MM喜欢的菜品的编号。菜品编号为1到m。
输出描述 Output Description
共包含T行,每行“Yes”或“No”。“Yes”表示存在一种方案,“No”表示不存在。
样例输入 Sample Input
2
3 4
2 2 4
1 3
1 2
5 4
2 1 3
2 2 4
1 2
1 3
1 4
样例输出 Sample Output
No
Yes
数据范围及提示 Data Size & Hint
对于30%的数据:N ≤ 16。
另有30%的数据:M ≤ 2。
对于100%的数据:1 ≤ T ≤ 10,1 ≤ N ≤ 500,1 ≤ M ≤ 30。
这题算是按照自己的思路写出来的。。。
首先,贾大神可贵地指出:任何大于等于四个人的桌子都可以拆成两个人的桌子。。这指引我们考虑两两配对。。(事实上我的这个方法在存在只能某几个三人组坐一起时应该是不对的。。)
将可以相邻的人连无向边
对于n是偶数,我们判断一下这个图的最小路径覆盖是否为边数除以二,如果是,那么我们就有使最小路径覆盖的边的端点的人两两一桌的方案了。n如果是奇数,枚举拆一个点,看剩下偶数个点是否满足刚才条件,再看最后拆的点能否和某人有边,如果有,就是yes
这样把数组开够之后,3个WA,一个T
鞠大神搞到AC代码之后,我们通过对拍发现,单独的点要想和某两人做一桌,必须和两人都可!!而不是一人!!!在匹配时记录这个点和哪个点匹配。。再判断。。
1个WA,1个T
我们终于发现匹配时得到的错误匹配要及时复原为0。。这样就不WA了。。。至于T的点,m=2,构成二分图,大概是可连的边太多。。所以直接判断两边的结点数一不一样。
我的这个方法好像和那个AC代码有很大偏差。。它不仅代码短,而且快,空间也少。。。。
总之我的脑残与日俱增。
label 10; type edge=record y,res,pre:longint;end; var a:array[0..2500000]of edge; last,q,level,cur:array[0..5000]of longint; vis,least:array[0..5000]of boolean; mm:array[0..1000,0..30]of boolean; flag:array[0..600,0..600]of boolean; e1,e2:array[0..3500000]of longint; pair:array[0..600]of longint; n,m,i,j,k,s,t,tt,tot,tote:longint; function min(a,b:longint):longint; begin if a<b then exit(a);exit(b); end; procedure insert(x,y,z:longint); begin inc(tot); a[tot].y:=y; a[tot].res:=z; a[tot].pre:=last[x]; last[x]:=tot; inc(tot); a[tot].y:=x; a[tot].res:=0; a[tot].pre:=last[y]; last[y]:=tot; end; function bfs:boolean; var h,tail,x,y,k:longint; begin fillchar(vis,sizeof(vis),false); fillchar(level,sizeof(level),0); vis[s]:=true; level[s]:=1; h:=0; tail:=1; q[0]:=s; while h<>tail do begin x:=q[h]; inc(h); k:=last[x]; while k<>0 do begin y:=a[k].y; if (a[k].res<>0)and(not vis[y]) then begin level[y]:=level[x]+1; vis[y]:=true; q[tail]:=y; inc(tail); end; k:=a[k].pre; end; end; exit(vis[t]); end; function dfs(x,f:longint):longint; var flow,k,y,ans,xx,yy:longint; function hehe:boolean; begin if (x>0)and(x<=n)and(y>=n+1)and(y<t) then exit(true); if (y>0)and(y<=n)and(x>=n+1)and(x<t) then exit(true); exit(false); end; begin ans:=0; if (x=t)or(f=0) then exit(f); //writeln(x); k:=cur[x]; while k<>0 do begin y:=a[k].y; if level[y]=level[x]+1 then begin flow:=dfs(y,min(f,a[k].res)); if flow<>0 then begin dec(a[k].res,flow); inc(a[k xor 1].res,flow); inc(ans,flow); dec(f,flow); yy:=y;xx:=x; if hehe then begin if y>x then yy:=y-n else xx:=xx-n; //writeln('tmpp',yy,' ',xx); pair[pair[xx]]:=0; pair[pair[yy]]:=0; pair[xx]:=yy; pair[yy]:=xx; end; if f=0 then break; end; end; //if hehe then writeln('hehe'); k:=a[k].pre; cur[x]:=k; end; exit(ans); end; function check(a,b:longint):boolean; var i:longint; begin for i:=1 to m do if mm[a][i] and mm[b][i] then exit(false);//(...=...) exit(true); end; function remove(z:longint):boolean; var i,j,ans,res,nn:longint; begin //writeln(z); ans:=0; fillchar(last,sizeof(last),0); tot:=1; for i:=1 to tote do if (e1[i]<>z)and(e2[i]<>z) then begin insert(e1[i],e2[i]+n,1); insert(e2[i],e1[i]+n,1); end; s:=0; t:=n<<1+1; for i:=1 to n do insert(s,i,1); for i:=1 to n do insert(i+n,t,1); //fillchar(pair,sizeof(pair),0); while bfs do begin fillchar(pair,sizeof(pair),0); cur:=last; inc(ans,dfs(s,maxlongint)); end; if z<>3000 then nn:=n-1 else nn:=n; res:=nn-ans>>1; if res<>nn>>1 then exit(false); if z=3000 then exit(true); for i:=1 to n do if flag[i,z] then if flag[pair[i],z] then begin //for j:=1 to n do write(pair[j],' '); exit(true); end; exit(false); end; procedure special; var c:array[0..2]of longint; i,j,k:longint; begin c[1]:=0;c[2]:=0; for i:=1 to n do begin read(k); if k=2 then begin writeln('No');exit;end; if k=0 then continue; read(k); inc(c[k]); end; if c[1]<>c[2] then writeln('No') else writeln('Yes'); end; begin readln(tt); 10: while tt<>0 do///tt begin dec(tt); readln(n,m); if m=2 then begin special;continue;end; fillchar(mm,sizeof(mm),false); fillchar(least,sizeof(least),false); tote:=0; fillchar(e1,sizeof(e1),0); fillchar(e2,sizeof(e2),0); fillchar(flag,sizeof(flag),false); for i:=1 to n do begin read(j); while j<>0 do begin dec(j); read(k); //if k=0 then break; mm[i][k]:=true; end; for k:=1 to i-1 do if check(i,k) then begin //writeln(i,k); flag[i,k]:=true; flag[k,i]:=true; inc(tote); e1[tote]:=i; e2[tote]:=k; end; readln; end; if n=3 then begin if check(1,2) and check(2,3) and check(1,3) then writeln('Yes') else writeln('No'); continue; end; if odd(n) then begin for i:=1 to n do if remove(i) then begin writeln('Yes');goto 10;end; writeln('No'); end else if remove(3000) then writeln('Yes') else writeln('No'); end; close(input);close(output); end.
相关文章推荐
- 站在烦恼里仰望幸福
- CODEVS 1850 (BZOJ 1005) 明明的烦恼 Prüfer 序列
- 站在烦恼里仰望幸福
- 站在烦恼里仰望幸福
- [做一个幸福的记号 忘了琐碎的烦恼]西兰花猪柳
- 就业困难期,他们面临着幸福的烦恼
- CodeVS1513 皇帝的烦恼
- 【codevs 2342】[2007年省队选拔赛上海市队选拔赛] 园丁的烦恼
- 站在烦恼里仰望幸福
- 烦恼也是一种幸福
- codevs 1488GangGang的烦恼
- 云存储带来哪些幸福的烦恼?
- 站在烦恼里仰望幸福
- 【日常学习】【读入优化】codevs2555 a+b=?题解
- 帝都It男的幸福一天
- 【codevs】p1010 过河卒
- 【codevs2822】爱在心中 tarjan 缩点+理解
- CODEVS 1004四子连棋
- Codevs题目1191 数轴染色 (线段树)
- 2015.9.11模拟赛 codevs 4160【会玩的】