jzoj3782 [NOIP2014模拟8.17] 组队
2018-02-03 19:31
330 查看
Description
你的任务是将一群人分到两个队伍中,使得:1、每个人都属于一个队伍。
2、每个队伍至少有一个人。
3、每个队伍的任意一个人都认识其他人。
4、两支队伍的人数尽可能接近。
这个任务可能有多组解,你可以输出任意一种。
注意:认识是单向的且没有传递性。
对于分值为 30%的数据,N <= 15
对于剩余分值为 70%的数据,N <= 100
[评分标准]
该题采用捆绑测试点评测的方式,即一组测试点包括许多测试点,对于每组测试点,你的必须通过该组测试点下的所有单个测试点才能得到全部分数,任意测试点错误都会导致该组测试点不得分。
该测试方式只为了提高测试准确度,并不会对选手的时间限制等造成影响。
即选手在编写程序时不需要考虑任何额外的操作。
Solution
考试的时候盯着100的n看光想最小割了可以转化为经典的2-sat模型,若两人无论如何都不能分在一组就连一条无向边。对于每个连通块单独讨论,如果不能黑白染色就无解。dp[k][i][j]表示能否实现前k个连通块一组分了i人另一组分了j人,转移的时候记录方案即可
捆绑数据真恶心,只有四种得分
Code
#include <stdio.h> #include <string.h> #include <stack> #define rep(i,st,ed) for (int i=st;i<=ed;++i) #define drp(i,st,ed) for (int i=st;i>=ed;--i) const int N=205; const int E=50005; struct edge{int x,y,next;}e[E]; bool rc ,inStack ,vis ; int dfn ,low ,scc ; int col ,a ,b ; int f ,rec ; int ls ,edCnt; std:: stack<int> stack; bool flag; void addEdge(int x,int y) { e[++edCnt]=(edge){x,y,ls[x]}; ls[x]=edCnt; e[++edCnt]=(edge){y,x,ls[y]}; ls[y]=edCnt; // printf("%d %d\n", x,y); } void color(int now,int id) { if (!flag) return ; vis[now]=1; col[now]=id; scc[now]=scc[0]; for (int i=ls[now];i;i=e[i].next) { if (!vis[e[i].y]) color(e[i].y,id^1); else if (col[e[i].y]==id) { flag=false; return ; } } } void build(int n) { rep(i,1,n) { rep(j,i+1,n) { if (!rc[i][j]||!rc[j][i]) { addEdge(i,j); } } } } void dp(int n) { f[0][0][0]=1; rep(k,1,scc[0]) { drp(i,n,0) { drp(j,n,0) { if (i==0&&j==0) continue; if (i>=a[k]&&j>=b[k]&&f[k-1][i-a[k]][j-b[k]]) { f[k][i][j]=1; rec[k][i][j]=1; } if (i>=b[k]&&j>=a[k]&&f[k-1][i-b[k]][j-a[k]]) { f[k][i][j]=1; rec[k][i][j]=2; } } } } } int main(void) { freopen("data.in","r",stdin); int n; scanf("%d",&n); rep(i,1,n) { int x; scanf("%d",&x); while (x) { rc[i][x]=1; scanf("%d",&x); } } build(n); flag=true; rep(i,1,n) { if (!vis[i]) { scc[0]++; color(i,1); } if (!flag) { puts("-1"); return 0; } } rep(i,1,n) { a[scc[i]]+=(col[i]==1); b[scc[i]]+=(col[i]==0); } dp(n); // puts(""); // rep(i,1,scc[0]) printf("%d %d\n", a[i],b[i]); // puts(""); // printf("%d %d\n", rec[2][2][3], rec[1][1][3]); drp(i,n/2,1) { int ti=i,tj=n-i; if (f[scc[0]][ti][tj]) { printf("%d ", ti); drp(k,scc[0],1) { rep(j,1,n) { if (scc[j]==k&&col[j]+1!=rec[k][ti][tj]) printf("%d ", j); } if (rec[k][ti][tj]==1) { ti-=a[k]; tj-=b[k]; } else if (rec[k][ti][tj]==2) { ti-=b[k]; tj-=a[k]; } } ti=i,tj=n-i; printf("\n%d ", tj); drp(k,scc[0],1) { rep(j,1,n) { if (scc[j]==k&&col[j]+1==rec[k][ti][tj]) printf("%d ", j); } if (rec[k][ti][tj]==1) { ti-=a[k]; tj-=b[k]; } else if (rec[k][ti][tj]==2) { ti-=b[k]; tj-=a[k]; } } return 0; } } return 0; }
相关文章推荐
- JZOJ3782. 【NOIP2014模拟8.17】组队
- jzoj3782 【NOIP2014模拟8.17】组队 (特殊情况的2sat,dp)
- JZOJ 3782. 【NOIP2014模拟8.17】组队
- 【NOIP2014模拟8.17】Magical GCD
- 【NOIP2014模拟8.17】Magical GCD
- 【NOIP2014模拟8.17】Magical GCD//2018.2.5
- 【NOIP2014模拟8.17】Magical GCD
- 【NOIP2014模拟8.17】Multiset //2018.2.5
- NOIP2014 Day1T1生活大爆炸版石头剪刀布 模拟
- Matrix 【NOIP2016提高A组模拟8.17】
- 【JZOJ4711】【NOIP2016提高A组模拟8.17】Binary
- [NOIP2014][vijos1913]螺旋矩阵(模拟)
- NOIP2014模拟 8.12
- 【NOIP2014模拟8.21】签到题3 jzoj 3797 树链剖分
- jzoj3929【NOIP2014模拟11.6】创世纪(图论,bfs,贪心)
- 3928. 【NOIP2014模拟11.6】射击 (Standard IO)
- jzoj5290 【NOIP2017提高组A组模拟8.17】行程的交集 (树上路径交,dfs序+树状数组维护姿势)
- 【JZOJ4710】【NOIP2016提高A组模拟8.17】Value
- 【NOIP2014模拟8.15】城市街区
- JZOJ 3824【NOIP2014模拟9.9】渴