JZOJ3782. 【NOIP2014模拟8.17】组队
2018-02-02 22:17
337 查看
Description
你的任务是将一群人分到两个队伍中,使得:1、每个人都属于一个队伍。
2、每个队伍至少有一个人。
3、每个队伍的任意一个人都认识其他人。
4、两支队伍的人数尽可能接近。
这个任务可能有多组解,你可以输出任意一种。
注意:认识是单向的且没有传递性。
Input
第一行为一个整数N,表示总人数。接下来为N行,每行多个整数x,第i + 1行描述编号为i的人认识x。每行以 0 结尾。
Output
如果无解输出−1;否则输出包含两行, 每行的第一个数字表示该队伍的总人数k,后面接着k个数字,表示被分到该队伍的人。Sample Input
52 3 5 0
1 4 5 3 0
1 2 5 0
1 2 3 0
4 3 2 1 0
Sample Output
3 1 3 52 2 4
Data Constraint
对于分值为 30%的数据,N <= 15对于剩余分值为 70%的数据,N <= 100
题解
根据相互认识的情况进行连边,就不能相互认识的人之间连一条双向边。
这样就会产生一些联通块,
就对这些联通块进行黑白染色,
一条边的两个短板不能为相同的颜色,
如果相同,就是无解。
现在就应该对这些染色之后的点进行分类了。
设gi,j表示当前是在第i个联通块,分到队列1中的点的个数为j。
0:表示不存在一种方案满足条件。
1:表示存在一种方案满足条件,这种方案为将第i个联通块里面染成黑色的点选入队列1中。
2:表示存在一种方案满足条件,这种方案为将第i个联通块里面染成白色的点选入队列1中。
最后通过这个数组的状态,将对应队列的点输出。
code
#include<queue> #include<cstdio> #include<iostream> #include<algorithm> #include <cstring> #include <string.h> #include <cmath> #include <math.h> #include <time.h> #define ll long long #define N 103 #define M 103 #define db double #define P putchar #define G getchar #define inf 998244353 using namespace std; char ch; void read(int &n) { n=0; ch=G(); while((ch<'0' || ch>'9') && ch!='-')ch=G(); ll w=1; if(ch=='-')w=-1,ch=G(); while('0'<=ch && ch<='9')n=(n<<3)+(n<<1)+ch-'0',ch=G(); n*=w; } int max(int a,int b){return a>b?a:b;} int min(int a,int b){return a<b?a:b;} int abs(int x){return x<0?-x:x;} ll sqr(ll x){return x*x;} void write(ll x){if(x>9) write(x/10);P(x%10+'0');} int n,t,f ,q ,bel ,cnt,s[3] ,head,tail,sx,sy,p ,ans; bool bz ,pd; int g ; void color(int x) { f[q[tail=1]=x]=1; head=0; while(head<tail) { x=q[++head]; s[f[x]][bel[x]=cnt]++; for(int i=1;i<=n;i++) if(bz[i][x] || bz[x][i]) { if(f[i]==f[x]) { pd=1; return; } if(f[i]==0) { f[i]=3-f[x]; q[++tail]=i; } } } } int main() { freopen("teams.in","r",stdin); freopen("teams.out","w",stdout); memset(bz,1,sizeof(bz)); read(n); for(int i=1;i<=n;i++) { for(read(t);t;read(t))bz[i][t]=0; bz[i][i]=0; } memset(f,0,sizeof(f)); pd=0; for(int i=1;i<=n;i++) if(f[i]==0)cnt++,color(i); if(pd) { P('-'),P('1'); return 0; } g[0][0]=1; for(int i=1;i<=cnt;i++) for(int j=min(s[1][i],s[2][i]);j<=n;j++) { if(j>=s[1][i] && g[i-1][j-s[1][i]])g[i][j]=1; if(j>=s[2][i] && g[i-1][j-s[2][i]])g[i][j]=2; } sx=n;sy=0; for(int i=1;i<=n;i++) if(g[cnt][i]) if(abs(i*2-n)<=abs(sx-sy))sx=i,sy=n-i; write(sx),P(' '); for(int i=cnt;i && sx;i--) { p[i]=g[i][sx]; sx-=s[p[i]][i]; } for(int i=1;i<=n;i++) if((f[i]+p[bel[i]])%2==0)write(i),P(' '); P('\n'); write(sy),P(' '); for(int i=1;i<=n;i++) if((f[i]+p[bel[i]])&1)write(i),P(' '); return 0; }
相关文章推荐
- jzoj3782 【NOIP2014模拟8.17】组队 (特殊情况的2sat,dp)
- JZOJ 3782. 【NOIP2014模拟8.17】组队
- jzoj3782 [NOIP2014模拟8.17] 组队
- JZOJ.4709【NOIP2016提高A组模拟8.17】Matrix
- jzoj. 3928. 【NOIP2014模拟11.6】射击
- jzoj3929【NOIP2014模拟11.6】创世纪(图论,bfs,贪心)
- [jzoj]3889. 【NOIP2014模拟10.25B组】序列问题(DP的各种方法+细节+详细分析)
- JZOJ 4711 Binary【NOIP2016提高A组模拟8.17】
- 【NOIP2014模拟8.17】Magical GCD
- JZOJ 3823. 【NOIP2014模拟9.9】遇见
- 【JZOJ 3823】【NOIP2014模拟9.9】遇见
- 【jzoj5289】【NOIP2017提高组A组模拟8.17】【偷笑】【数据结构】
- JZOJ 3807. 【NOIP2014模拟8.25】地砖铺设
- JZOJ 3839【NOIP2014模拟9.14】Baby Step
- 【NOIP2014模拟8.21】签到题3 jzoj 3797 树链剖分
- 【jzoj5288】【NOIP2017提高组A组模拟8.17】【球场大佬】
- jzoj. 3929. 【NOIP2014模拟11.6】创世纪
- JZOJ 3806. 【NOIP2014模拟8.24】小X 的道路修建
- JZOJ 4709 Matrix【NOIP2016提高A组模拟8.17】
- JZOJ 3775. 【NOIP2014模拟8.15】因子的排列