POJ1112——Team Them Up!(动态规划,二分图判定)
来源:互联网 发布:淘宝客服服务流程 编辑:程序博客网 时间:2024/06/06 09:21
Team Them Up!
Time Limit: 1000MS
Memory Limit: 10000KTotal Submissions: 7454
Accepted: 2011
Special Judge
Memory Limit: 10000KTotal Submissions: 7454
Accepted: 2011
Special Judge
Description
Your task is to divide a number of persons into two teams, in such a way, that:
everyone belongs to one of the teams;
every team has at least one member;
every person in the team knows every other person in his team;
teams are as close in their sizes as possible.
This task may have many solutions. You are to find and output any solution, or to report that the solution does not exist.
everyone belongs to one of the teams;
every team has at least one member;
every person in the team knows every other person in his team;
teams are as close in their sizes as possible.
This task may have many solutions. You are to find and output any solution, or to report that the solution does not exist.
Input
For simplicity, all persons are assigned a unique integer identifier from 1 to N.
The first line in the input file contains a single integer number N (2 <= N <= 100) - the total number of persons to divide into teams, followed by N lines - one line per person in ascending order of their identifiers. Each line contains the list of distinct numbers Aij (1 <= Aij <= N, Aij != i) separated by spaces. The list represents identifiers of persons that ith person knows. The list is terminated by 0.
The first line in the input file contains a single integer number N (2 <= N <= 100) - the total number of persons to divide into teams, followed by N lines - one line per person in ascending order of their identifiers. Each line contains the list of distinct numbers Aij (1 <= Aij <= N, Aij != i) separated by spaces. The list represents identifiers of persons that ith person knows. The list is terminated by 0.
Output
If the solution to the problem does not exist, then write a single message "No solution" (without quotes) to the output file. Otherwise write a solution on two lines. On the first line of the output file write the number of persons in the first team, followed by the identifiers of persons in the first team, placing one space before each identifier. On the second line describe the second team in the same way. You may write teams and identifiers of persons in a team in any order.
Sample Input
52 3 5 01 4 5 3 01 2 5 01 2 3 04 3 2 1 0
Sample Output
3 1 3 52 2 4
题意:
你的任务是把一些人 分成两组, 需要满足以下条件:
每个人都在一个队伍里
每个人都在一个队伍里
每个队至少一个人;
每个在队里的人都认识队里的其他人;
两个队伍相差的人数尽量少.
可能有多种解,输出其中任何一种;或者输出无解
每个在队里的人都认识队里的其他人;
两个队伍相差的人数尽量少.
可能有多种解,输出其中任何一种;或者输出无解
思路:首先得判断出谁和谁一定不能在一组,很自然地想到二分图染色。只有两个人相互认识才能在同一个队伍。所以针对不能在同一个队伍地人连边,然后二分图染色。
染色的过程中得统计不同颜色有多少人,哪些人。分成不同的连通块。
然后问题就转化成了,比如有m个连通块,x[i]和y[i]代表不同的颜色。对于每个连通块,需要在x和y中选一个,统计总人数,使得最后两组人数差最小。
我觉得我写得好像很复杂,但因为数据量很小所以也能过。
dp[i][j]表示一组i个人,一组j个人的状态能否达到。
ans[i][j][k]表示该状态可以达到的情况下,第k个连通块选了x还是y。
最后再算一下最小值,更新结果。
写得太浪了。。。
#include <stdio.h>#include <string.h>#include <vector>#include <queue>#include <algorithm>#include <cmath>using namespace std;#define MAXN 110#define INF 1000000007vector <int> G[MAXN];int V;int color[MAXN];vector <int> x[MAXN];vector <int> y[MAXN];int d[MAXN][MAXN];int dp[MAXN][MAXN];int ans[MAXN][MAXN][MAXN];int num=0;bool dfs(int v,int c){ color[v]=c; if(c>0) x[num].push_back(v); else y[num].push_back(v); for(int i=0;i<G[v].size();i++){ if(color[G[v][i]]==c) return false; if(color[G[v][i]]==0&&!dfs(G[v][i],-c)){ return false; } } return true;}int main(){ int n; scanf("%d",&n); for(int i=1;i<=n;i++){ int t; while(scanf("%d",&t)&&t){ d[i][t]=1; } } for(int i=1;i<n;i++){ for(int j=i+1;j<=n;j++){ if(!d[i][j]||!d[j][i]) { G[i].push_back(j); G[j].push_back(i); } } } for(int i=1;i<=n;i++){ if(!color[i]){ if(dfs(i,1)){ num++; } else{ printf("No solution\n"); return 0; } } } memset(dp,0,sizeof(dp)); vector <int>r1; vector <int> r2; int m=n/2; dp[0][0]=1; memset(ans,-1,sizeof(ans)); for(int k=0;k<num;k++){ for(int i=0;i<=n;i++){ for(int j=0;j<=n;j++){ if(dp[i][j]&&ans[i][j][k]==-1){ int a=x[k].size(),b=y[k].size(); if(dp[i+a][j+b]==0){ dp[i+a][j+b]=1; ans[i+a][j+b][k]=0; //printf("<<<%d %d %d >>>\n",i+a,j+b,ans[i+a][j+b][k]); for(int t=0;t<k;t++) ans[i+a][j+b][t]=ans[i][j][t]; } if(dp[i+b][j+a]==0){ dp[i+b][j+a]=1; ans[i+b][j+a][k]=1; //printf("<<<%d %d %d >>>\n",i+b,j+a,ans[i+b][j+a][k]); for(int t=0;t<k;t++) ans[i+b][j+a][t]=ans[i][j][t]; } } } } } int min_f=INF; for(int i=1;i<=n/2;i++){ int j=n-i; if(dp[i][j]){ if((j-i)<min_f){ r1.clear(); r2.clear(); for(int k=0;k<num;k++){ if(ans[i][j][k]==0){ for(int s=0;s<x[k].size();s++){ r1.push_back(x[k][s]); } for(int s=0;s<y[k].size();s++){ r2.push_back(y[k][s]); } } else{ for(int s=0;s<y[k].size();s++){ r1.push_back(y[k][s]); } for(int s=0;s<x[k].size();s++){ r2.push_back(x[k][s]); } } } } } } printf("%d ",r1.size()); for(int i=0;i<r1.size();i++) printf(" %d",r1[i]); printf("\n"); printf("%d ",r2.size()); for(int i=0;i<r2.size();i++) printf(" %d",r2[i]); printf("\n");}
0 0
- POJ1112——Team Them Up!(动态规划,二分图判定)
- poj1112 Team Them Up!(二分图染色+dp)
- poj1112 Team Them Up!
- poj1112 Team Them Up!
- [ZOJ1462][POJ1112] Team Them Up!
- 100道动态规划——16 UVA 1627 Team them up! 二分图,背包,不过关键还是学会转化
- POJ1112 Team Them Up! 连通图 染色 DP
- 【练习试题】分组(poj1112 Team Them Up!)
- poj 1112 二部图判定+背包(team them up)
- POJ 1112 Team Them Up! (图(反图)染色+连通分量+动态规划) 解释代码
- Uva 1627 Team them up!(dp+二分图染色)
- 【暑假】[深入动态规划]UVa 1627 Team them up!
- ZOJ 1462 Team Them Up! (二分图+路径保存DP)
- poj 1112 Team Them Up! 二分图染色+dp
- uva 1627 Team them up! 二分图 + 连通分量 + 背包
- POJ 1112 Team Them Up! (二分图染色+连通分量+DP)
- UVA 1627 Team them up!(二分图染色+并查集+背包)
- poj 1112 Team Them Up! (补图+dp)
- 手机端网页处理手机返回键
- intelli IDEA j安装scala插件
- BaseFragment的抽取
- find the safest road hd 1596
- Windows平台编译libevent
- POJ1112——Team Them Up!(动态规划,二分图判定)
- css定义table表格边框技巧分享
- C/C++传入数组及怎样限定传入数组的大小
- PCL中std::numeric_limits::max()编译错误
- 一步步将vim改造成C/C++开发环境(IDE)
- 推荐系统的相关算法SVD
- 深入浅出spring IOC中三种依赖注入方式
- Android闹钟开发问题点记录
- VS中DEBUG和RELEASE运行结果不一样