码迷,mamicode.com
首页 > 其他好文 > 详细

Team them up!

时间:2015-10-17 22:14:53      阅读:253      评论:0      收藏:0      [点我收藏+]

标签:

题意:

给出n个人以及认识其他人的情况,现在要把所有人分成两队,每队至少一人,求使两队人数差距最小且每队内部的人都相互认识的分队情况。

分析:

这道题让我学习到了不少,首先看到使差距最小就想到了背包,但是不会表示分队情况。看了别人的思路,这个很明显是要判断是否是二分图,让不是相互认识的两人连一条边,若不是二分图则不能分成两队。利用染色法判断二分图,则每个连通分量都包含0,1两个集合。

dp[i][j]表示i个联通分量能组成符合条件的人数为j的一队,par[i][j]记录路径

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <queue>
#include <stack>
#include <cstdio>
#include <vector>
#include <string>
#include <cctype>
#include <complex>
#include <cassert>
#include <utility>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
#define lson l,m,rt<<1
#define pi acos(-1.0)
#define rson m+1,r,rt<<11
#define All 1,N,1
#define N 110
#define read freopen("in.txt", "r", stdin)
const ll  INFll = 0x3f3f3f3f3f3f3f3fLL;
const int INF= 0x7ffffff;
const int mod =  1000000007;
int n,tim,num;
int dp[N][N],par[N][N],mapc[N][N],part[N][2];
int color[N],dfn[N],f[N],road[N][N][2];
vector<int>e[N];
int dfs(int u){
    dfn[u]=++tim;
    road[num][++part[num][color[u]]][color[u]]=u;
    for(int i=0;i<e[u].size();++i){
            int v=e[u][i];
        if(dfn[v]==0){
            color[v]=(!color[u]);
            if(dfs(v)==0)return 0;
        }
        else{
            if(v!=u&&color[u]==color[v])return 0;
        }
    }
    return 1;
}
void hand(){
    int v;
    for(v=n/2;v>=0;--v){
        if(dp[num][v])
            break;
    }
    if(v==0){printf("No solution\n");return;}
    memset(f,0,sizeof(f));
    int tmp=v,t;
    for(int i=num;i>=0;--i){
        t=par[i][tmp];
        tmp-=part[i][t];
        for(int j=1;j<=part[i][t];++j)
            f[road[i][j][t]]=1;
    }
    printf("%d",v);
    for(int i=1;i<=n;++i)
        if(f[i])
        printf(" %d",i);
    printf("\n");
    printf("%d",n-v);
    for(int i=1;i<=n;++i)
        if(!f[i])
        printf(" %d",i);
    printf("\n");
}
void solve(){
    memset(part,0,sizeof(part));
    memset(color,0,sizeof(color));
    memset(dfn,0,sizeof(dfn));
    memset(dp,0,sizeof(dp));
    tim=num=0;
    int k;
    for(k=1;k<=n;++k){
        if(!dfn[k]){
            ++num;
            if(dfs(k)==0)break;
        }
    }
    if(k<=n)printf("No solution\n");
    else{
        dp[0][0]=1;
        for(int i=1;i<=num;++i)
        for(int j=0;j<=n/2;++j){
            int tmp=j-part[i][0];
            if(tmp>=0&&dp[i-1][tmp]){
                dp[i][j]=1;
                par[i][j]=0;
            }
            tmp=j-part[i][1];
            if(tmp>=0&&dp[i-1][tmp])
            {
                dp[i][j]=1;
                par[i][j]=1;
            }
        }
        hand();
    }
}
int main()
{
    int ca=0;
    scanf("%d",&ca);
    while(ca--){
        scanf("%d",&n);
        int a;
        memset(mapc,0,sizeof(mapc));
        for(int i=1;i<=n;++i)
            e[i].clear();
        for(int i=1;i<=n;++i){
            while(~scanf("%d",&a)&&a){
                mapc[i][a]=1;
            }
        }
        for(int i=1;i<=n;++i)
            for(int j=i+1;j<=n;++j)
        if(mapc[i][j]==0||mapc[j][i]==0){
            e[i].push_back(j);
            e[j].push_back(i);
        }
        solve();
        if(ca)printf("\n");
    }
return 0;
}

 

Team them up!

标签:

原文地址:http://www.cnblogs.com/zsf123/p/4888350.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!