Description
你的任務是將一羣人分到兩個隊伍中,使得:
1、每個人都屬於一個隊伍。
2、每個隊伍至少有一個人。
3、每個隊伍的任意一個人都認識其他人。
4、兩支隊伍的人數儘可能接近。
這個任務可能有多組解,你可以輸出任意一種。
注意:認識是單向的且沒有傳遞性。
Input
第一行爲一個整數N,表示總人數。
接下來爲N行,每行多個整數x,第i + 1行描述編號爲i的人認識x。每行以 0 結尾。
Output
如果無解輸出−1;否則輸出包含兩行, 每行的第一個數字表示該隊伍的總人數k,後面接着k個數字,表示被分到該隊伍的人。
Sample Input
5
2 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 5
2 2 4
Data Constraint
對於分值爲 30%的數據,N <= 15
對於剩餘分值爲 70%的數據,N <= 100
Solution
我們先把不能相連的弄出來
那顯然他們要放在不同的集合
這樣子搞一搞之後
我們就可以dp了
設一個0/1狀態f[h][i][j]表示做完前h個小團塊 第一個集合放i個 第二個集合放j個是否可行
dp的時候保留一下方案即可
Code
#include <cstdio>
#include <cstring>
#include <algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fd(i,a,b) for(i=a;i>=b;i--)
using namespace std;
int n,i,j,stm,h,k,cnt1,cnt2,a,b,f[105][105][105],x,y,xx,yy,k1,k2,z;
int aa[105][105],bz[105],g[105][2],un[105][105],pr[105],w[105],w1[105];
struct edge{
int x,y;
} bf[105][105][105];
int read(){
int sum=0;
char c=getchar();
while (c<'0'||c>'9') c=getchar();
while (c>='0'&&c<='9'){
sum=sum*10+c-'0';
c=getchar();}
return sum;
}
void dfs(int x){
int i,y;
fo(i,1,un[x][0]){
y=un[x][i];
if (bz[y]){
if (bz[y]==bz[x]) { printf("-1\n"); exit(0);}
} else {
bz[y]=(bz[x]==stm)?stm+1:stm;
if (bz[y]==stm) cnt1++; else cnt2++;
dfs(y);}
}
}
int main(){
//freopen("1.in","r",stdin);
//freopen("1.out","w",stdout);
n=read();
fo(i,1,n){
k=read();
while (k) aa[i][k]=1,k=read();}
fo(i,1,n)
fo(j,1,n)
if (i!=j&&(!aa[i][j]||!aa[j][i])) un[i][++un[i][0]]=j;
fo(i,1,n){
if (bz[i]) continue;
stm+=2,cnt2=0,cnt1=1,bz[i]=stm,dfs(i);
g[++h][0]=cnt1,g[h][1]=cnt2;
pr[h]=stm;}
f[0][0][0]=1;
fo(i,1,h)
fo(a,0,n)
fo(b,0,n) {
if (a+g[i][0]<=n&&b+g[i][1]<=n){
f[i][a+g[i][0]][b+g[i][1]]|=f[i-1][a][b];
if (f[i-1][a][b]) {
bf[i][a+g[i][0]][b+g[i][1]].x=a;
bf[i][a+g[i][0]][b+g[i][1]].y=b;}
}
if (a+g[i][1]<=n&&b+g[i][0]<=n){
f[i][a+g[i][1]][b+g[i][0]]|=f[i-1][a][b];
if (f[i-1][a][b]){
bf[i][a+g[i][1]][b+g[i][0]].x=a;
bf[i][a+g[i][1]][b+g[i][0]].y=b;}
}
}
fd(i,n/2,1)
if (f[h][i][n-i]){
x=i,y=n-i;
fd(j,h,1){
xx=bf[j][x][y].x,yy=bf[j][x][y].y;
k1=pr[j],k2=k1+1;
if (x-xx==g[j][1]) swap(k1,k2);
fo(z,1,n) if (bz[z]==k1) w[++w[0]]=z;
else if (bz[z]==k2) w1[++w1[0]]=z;
x=xx,y=yy;
}
fo(j,0,w[0]) printf("%d ",w[j]);
printf("\n");
fo(j,0,w1[0]) printf("%d ",w1[j]);
printf("\n");
return 0;
}
}