P1285 队员分组(二分图+背包)

P1285 队员分组在这里插入图片描述

#include <iostream>
#include <string>
#include <complex>
#include <vector>
#include <stack>
#include <cstdio>
#include<functional>
#include<cmath>
#include<ctime>
#include<cstring>
#include<algorithm>
using namespace std;
typedef complex<double> cp;
#define ll long long
#define  re register
#define sci(x) scanf("%d",&x)
#define scl(x) scanf("%lld",&x)
#define scf(x) scanf("%lf",&x)
#define print(arr,n) for(int i=0;i<n;i++){for(int j=0;j<n;j++)printf("%d ",arr[i][j]);printf("\n");}
#define fo(a,b,c)for(int a=b;a<=c;a++)
#define getname(x) #x
const int maxn=1e4+5;
int adj[maxn],nex[maxn<<1],to[maxn<<1];
int bag[101][2][101];
int rel[101][101],n,x,vis[101],ops[101],tot,sz[101][2];
int dp[101][101],rec[101][101],ans1[101],ans2[101];
void add(int i,int j)
{
    nex[0]++;
    nex[nex[0]]=adj[i];
    adj[i]=nex[0];
    to[nex[0]]=j;
}
void adds(int i,int j)
{
    add(i,j);
    add(j,i);
}
bool bfs(int i)
{
    stack<int>st;
    st.push(i);
    ops[i]=1;
    bag[++sz[tot][1]][ops[i]][tot]=i;
    vis[i]=1;
    while(!st.empty()){
        int tp=st.top();
        st.pop();
        for(int k=adj[tp];k;k=nex[k]){
            int t=to[k];
            if(vis[t]){
                if(ops[t]==ops[tp])return false;
            }
            else {
                st.push(t);
                ops[t]=!ops[tp];
                bag[++sz[tot][ops[t]]][ops[t]][tot]=t;
                vis[t]=1;
            }
        }
    }
    tot++;
return true;
}
bool  solve()
{
        for(int i=0;i<n;i++){
            if(!vis[i]&&!bfs(i)){
                return true;
            }
        }
        for(int i=0;i<=tot;i++)
            for(int j=0;j<=n;j++)dp[i][j]=-1;dp[0][0]=0;
        for(int i=1;i<=tot;i++){
            int o=sz[i-1][0];
            int l=sz[i-1][1];
            for(int j=0;j<=n;j++){
                if(j>=o&&~dp[i-1][j-o]){
                    dp[i][j]=true;
                    rec[i][j]=0;
                }
                if(j>=l&&~dp[i-1][j-l]){
                    dp[i][j]=true;
                    rec[i][j]=1;
                }
            }
        }
        int fin=0;
        for(int i=n/2;i;i--){
            if(dp[tot][i]!=-1){
                fin=i;break;
            }
        }
        for(int j=tot;j;j--){
            int ch=rec[j][fin];
            int bs=sz[j-1][ch];
            for(int k=1;k<=bs;k++){
                ans1[++ans1[0]]=bag[k][ch][j-1];
            }fin-=sz[j-1][ch];
            ch=!ch;
            bs=sz[j-1][ch];
            for(int k=1;k<=bs;k++)
            {
                ans2[++ans2[0]]=bag[k][ch][j-1];
            }

        }
        sort(ans1+1,ans1+1+ans1[0]);
        sort(ans2+1,ans2+1+ans2[0]);
        return false;


}
void setR()
{
    sci(n);
    for(int i=0;i<n;i++){
    while(sci(x)&&x){rel[i][x-1]=1;}
    }
    for(int i=0;i<n;i++)
    for(int j=i+1;j<n;j++){
        if(!(rel[i][j]&&rel[j][i]))
            adds(i,j);
    }
}
int main()
{
        setR();
        if(solve()){
            printf("No solution");
        }
        else {
            printf("%d ",ans1[0]);
            for(int i=1;i<=ans1[0];i++){
                printf("%d ",ans1[i]+1);
            }
            printf("\n");
            printf("%d ",ans2[0]);
            for(int i=1;i<=ans2[0];i++){
            printf("%d ",ans2[i]+1);
            }
            printf("\n");
        }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值