https://cn.vjudge.net/problem/UVA-1627

题目

有n(n≤100)个人,把他们分成非空的两组,使得每个人都被分到一组,且同组中的人相互认识。要求两组的成员人数尽量接近。多解时输出任意方案,无解时输出No Solution。

例如,1认识2, 3, 5;2认识1, 3, 4, 5;3认识1, 2, 5,4认识1, 2, 3,5认识1, 2, 3, 4(注意4认识1但1不认识4),则可以分两组:{1,3,5}和{2,4}。

题解

不是互相认识的连边,然后保证一条边的两个人分到两个不同的组

一个连通分量的人可以存起来……那么类似于poj1417最后的dp部分

设$dp[i][j]$为前i个连通块,两组人数差为j时是否存在

因为j可能为负数,不方便迭代,于是改为设$dp[i][100+j]$

易证若差为j时存在,那么差为-j时也存在,于是最后只用枚举$dp[conn][100..100+n]$是否存在,然后按照dp相反的方向输出解(因为要看每一次的决策是什么)

AC代码

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3.  
  4. #define REP(r,x,y) for(register int r=(x); r<(y); r++)
  5. #define PER(r,x,y) for(register int r=(x); r>(y); r--)
  6. #define REPE(r,x,y) for(register int r=(x); r<=(y); r++)
  7. #define PERE(r,x,y) for(register int r=(x); r>=(y); r--)
  8. #ifdef sahdsg
  9. #define DBG(...) printf(__VA_ARGS__)
  10. #else
  11. #define DBG(...) (void)0
  12. #endif
  13. int n;
  14. int G[107][107];
  15. bool tmp[107];
  16. int v[107],conn=0,r[107];
  17. int vis[107];
  18. bool failed;
  19. int dp[107][207];
  20. int cho[107];
  21. inline int signx(int x, int k) {
  22. int ans=1;
  23. int t=x+1; if(t>n) t=1;
  24. vis[x]=k;
  25. do {
  26. if(G[x][t]) {
  27. if(!vis[t])
  28. ans-=signx(t,-k);
  29. else if(vis[t]!=-k) {
  30. failed = true;
  31. return 0;
  32. }
  33. }
  34. if(failed) return 0;
  35. t++; if(t>n) t=1;
  36. } while(t!=x);
  37. return ans;
  38. }
  39. int ansarr[107][2], ansn[2]={0,0};
  40. inline void anx(int x, int i) {
  41. ansarr[ansn[i]++][i]=x;
  42. int t=x+1; if(t>n) t=1;
  43. vis[x]=-2;
  44. do {
  45. if(G[x][t] && vis[t]!=-2) {
  46. anx(t, !i);
  47. }
  48. t++; if(t>n) t=1;
  49. } while(t!=x);
  50. }
  51. int main() {
  52. #ifdef sahdsg
  53. freopen("in.txt","r",stdin);
  54. #endif
  55. int t; scanf("%d", &t);
  56. while(0<t--) {
  57. scanf("%d", &n); memset(G,0,sizeof G); memset(vis,0,sizeof vis); conn=0;
  58. REPE(i,1,n) {
  59. int v;
  60. memset(tmp,0,sizeof tmp);
  61. tmp[i]=1;
  62. while(1) {
  63. scanf("%d", &v);
  64. if(v==0) break;
  65. tmp[v]=1;
  66. }
  67. REPE(j,1,n) if(tmp[j]==0) G[i][j]=G[j][i]=1;
  68. }
  69. failed = false;
  70. int a=0;
  71. REPE(i,1,n) {
  72. if(!vis[i]) {r[++conn]=i; v[conn]=signx(i,1);}
  73. if(failed) {
  74. goto _wa;
  75. }
  76. }
  77. #define in(x) ((x)<=200 && (x)>=0)
  78. memset(dp,0,sizeof dp);
  79. dp[0][100]=1;
  80. REPE(i,1,conn) {
  81. REPE(j,100-n,100+n) {
  82. if(in(j-v[i]) && dp[i-1][j-v[i]]) dp[i][j]=1;
  83. else if(in(j+v[i]) && dp[i-1][j+v[i]]) dp[i][j]=1;
  84. }
  85. }
  86. memset(ansn,0,sizeof ansn);
  87. for(; a<=n; a++) {
  88. if(dp[conn][100+a]) {
  89. break;
  90. }
  91. }
  92. PERE(i,conn,1) {
  93. if(in(100+a-v[i]) && dp[i-1][100+a-v[i]]) a-=v[i],anx(r[i],0);
  94. else if(in(100+a+v[i]) && dp[i-1][100+a+v[i]]) a+=v[i],anx(r[i],1);
  95. }
  96. #undef in
  97. REPE(j,0,1) {
  98. printf("%d", ansn[j]);
  99. REP(i,0,ansn[j]) {
  100. printf(" %d", ansarr[i][j]);
  101. }
  102. putchar('\n');
  103. }
  104. if(t) putchar('\n'); continue;
  105. _wa:
  106. puts("No solution"); if(t) putchar('\n'); continue;
  107. }
  108. return 0;
  109. }

UVA 1627 Team them up!的更多相关文章

  1. 【暑假】[深入动态规划]UVa 1627 Team them up!

    UVa 1627 Team them up! 题目: Team them up! Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Forma ...

  2. UVa 1627 - Team them up!——[0-1背包]

    Your task is to divide a number of persons into two teams, in such a way, that: everyone belongs to ...

  3. UVa 1627 Team them up! (01背包+二分图)

    题意:给n个分成两个组,保证每个组的人都相互认识,并且两组人数相差最少,给出一种方案. 析:首先我们可以知道如果某两个人不认识,那么他们肯定在不同的分组中,所以我们可以根据这个结论构造成一个图,如果两 ...

  4. UVA.540 Team Queue (队列)

    UVA.540 Team Queue (队列) 题意分析 有t个团队正在排队,每次来一个新人的时候,他可以插入到他最后一个队友的身后,如果没有他的队友,那么他只能插入到队伍的最后.题目中包含以下操作: ...

  5. 【Uva 1627】Team them up!

    [Link]: [Description] 给你n个人; 有一些人之间有认识关系 a认识b,b不一定认识a 让你把这n个人分成两组 使得这两组中的每一组: 组内的人与人之间都相互认识. 并且,使得两组 ...

  6. uva 540 - Team Queue(插队队列)

    首发:https://mp.csdn.net/mdeditor/80294426 例题5-6 团体队列(Team Queue,UVa540) 有t个团队的人正在排一个长队.每次新来一个人时,如果他有队 ...

  7. UVA 540 Team Queue(模拟+队列)

    题目代号:UVA 540 题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page ...

  8. UVa 540 Team Queue 【STL】

    题意:给出t个团体,这t个团体排在一起,每次新来一个x排队,如果在整个的团体队列中,有x的队友,那么x排在它的队友的后面,如果他没有队友,则排在长队的队尾 求给出的每一个出队命令,输出出队的人的编号 ...

  9. UVA 540 Team Queue

    思路:使用优先队列,按队伍出现的时刻和自身出现的时刻定义优先级,同时记录此时刻队列里是否有自己队伍的人,一开始没注意,wa了两发. #include<map> #include<qu ...

随机推荐

  1. Ajax请求中的async:false/true(同步/异步)的作用

    async. 默认是true,即为异步方式,$.Ajax执行后,会继续执行ajax后面的脚本,直到服务器端返回数据后,触发$.Ajax里的success方法,这时候执行的是两个线程.若要将其设置为fa ...

  2. 十分钟(小时)学习pandas

    十分钟学习pandas 一.导语 这篇文章从pandas官网翻译:链接,而且也有很多网友翻译过,而我为什么没去看他们的,而是去官网自己艰难翻译呢? 毕竟这是一个学习的过程,别人写的不如自己写的记忆深刻 ...

  3. Win10操作系统下Oracle VM VirtualBox6.0加载磁盘提示“发现无效设置”的解决方法(包括“不能桥接网卡”问题的解决方法)

    自从电脑换成Win10操作系统后,想借助VMBox处理一些事情,但是遇到了不能桥接网卡的问题,还以为是程序坏了,于是卸载重新安装,但是不行.接着又尝试在虚拟机里重新安装操作系统,还是不行. 然后百度了 ...

  4. centos6.3部署配置LVS主从

    LVS是Linux Virtual Server的简写,即Linux虚拟服务器,是一个虚拟的服务器集群系统.这个项目在1998年5月由章文嵩博士成立,是中国国内最早出现的自由软件项目之一.它的官方网址 ...

  5. MAC终端常用语法

    这篇文章的重点不在于说是对终端语法的讲解,而是方便大家做语法备忘. 方便查找对应终端语法.所以使用了表格形式对常用终端语法进行了汇总, 但是并没有很多的讲解部分. 当然了这里记录的也都是十分基础的语法 ...

  6. 理解ECS的概念和Unity中的ECS设计

    组合优于继承 ecs的概念很早就有了,最初的主要目的应该还是为了改善设计. e-c-s三者都有其意义,e-c是组合优于继承,主要用以改善oo的继承耦合过重以及多继承菱形问题. oop常见设计里,每个g ...

  7. SQLServer之数据类型解析

    数字 int.bigint.smallint 和 tinyint 使用整数数据的精确数字数据类型. 数据类型 范围 存储 tinyint 0 到 255. 1 字节 smallint -2^15 (- ...

  8. OKR源自德鲁克和格鲁夫,跟谷歌是天作之合:4星|《这就是OKR》

    这就是OKR,[美]约翰杜尔(John Doerr),中信出版社,9787508696881 作者以实习生的身份加入英特尔,跟格鲁夫有交集,见证了格鲁夫在英特尔创立OKR的过程和英特尔使用OKR作为管 ...

  9. Java基础——0 前言

  10. 【Teradata Utility】使用SQL Assistant导出导入数据

    1.导出 (1)选择菜单栏File,点击Export Results,输入导出数据的SQL: select * from etl_data.soure_table; (2)选择导出数据格式为txt或h ...