poj 1112 Team Them Up!

题目链接:http://poj.org/problem?id=1112

题目大意:把n个人分成两组;组内成员相互之间必须认识。做法是如果两个人不是相互都认识则建边,用dfs搜出连通分量,然后dp,具体见其他人的博客。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<string>
#include<queue>
#include<algorithm>
#include<vector>
#include<stack>
#include<list>
#include<iostream>
#include<map>
using namespace std;
#define inf 0x3f3f3f3f
#define Max 110
int max(int a,int b)
{
	return a>b?a:b;
}
int min(int a,int b)
{
	return a<b?a:b;
}
int f[Max],id;
int dp[Max][Max],mp[Max][Max];
int num[Max][2];
int cnt,tmp,co[Max],vst[Max],eid,p[Max],flag;
struct node
{
    int to,next;
}e[2*Max*Max];
void addedge(int u,int v)
{
    e[eid].to=v;
   // e[eid].len=len;
    e[eid].next=p[u];
    p[u]=eid++;
}
void dfs(int u)
{
    int v,i;
    for(i=p[u];i!=-1;i=e[i].next)
    {
        v=e[i].to;
        if(co[v]==co[u])
        {
            flag=1;
            return;
        }
        else if(co[v]!=-1)
            continue;
        v=e[i].to;
        f[v]=id;
        co[v]=co[u]^1;
        num[id][co[v]]++;
        dfs(v);
        if(flag)
            return;
    }
    if(flag)
        return;
}
int main()
{
    int n,u,v,i,j;
   // while(!=EOF)
   // {
        scanf("%d",&n);
        memset(co,-1,sizeof(co));
        memset(p,-1,sizeof(p));
        eid=0;
        for(i=1;i<=n;i++)
        {
            while(scanf("%d",&v),v)
            {
                mp[i][v]=1;
            }
        }
        for(i=1;i<=n;i++)
            for(j=1;j<=n;j++)
            {
                if(mp[i][j]&&mp[j][i])
                    continue;
                if(i==j)
                    continue;
                addedge(i,j);
                addedge(j,i);
            }
        id=1;
        flag=0;
       // printf("yyyy");
        for(i=1;i<=n;i++)
        {
            if(co[i]==-1)
            {
                co[i]=0;
                num[id][0]++;
                f[i]=id;
                dfs(i);
               // printf("cccc");
                if(flag==1)
                {
                    printf("No solution\n");
                    break;
                }
                id++;
            }
        }
        if(flag)return 0;;
        dp[0][0]=1;
        for(i=1;i<id;i++)
        {
            //int tmp1=num[id][0];
           // int tmp2=num[id][1];
            for(j=0;j<=n/2;j++)
            {
                if(dp[i-1][j])
                {
                    if(j+num[i][0]<=n/2)
                        dp[i][j+num[i][0]]=1;
                    if(j+num[i][1]<=n/2)
                        dp[i][j+num[i][1]]=1;
                }
            }
        }
        for(i=n/2;i>=0;i--)
        {
            if(dp[id-1][i]==1)
            {
                tmp=i;
                cnt=i;
                break;
            }
        }
        for(i=id-1;i>=1;i--)
        {
            int typ;
            if(tmp-num[i][0]>=0&&dp[i-1][tmp-num[i][0]])
            {
                typ=0;
                tmp=tmp-num[i][0];//continue;
            }
            else if(tmp-num[i][1]>=0&&dp[i-1][tmp-num[i][1]])
            {
                tmp=tmp-num[i][1];
                typ=1;
            }
            for(j=1;j<=n;j++)
            {
                if(f[j]==i&&co[j]==typ)
                    vst[j]=1;
            }
        }
        printf("%d ",cnt);
        for(i=1;i<=n;i++)
        {
            if(vst[i])
                printf("%d ",i);
        }
        puts("");
        printf("%d ",n-cnt);
        for(i=1;i<=n;i++)
        {
            if(!vst[i])
                printf("%d ",i);
        }
        puts("");
  //  }
}

 

 

你可能感兴趣的:(UP)