uva1627
来源:互联网 发布:淘宝店logo生成器 编辑:程序博客网 时间:2024/06/05 17:11
- 题目大意
- 思路
- 代码
- Hit
题目大意
传送门
有n个人,把他们分成非空的两组,使得每个人都被分到一组,并且同组的人要相互认识。要求两组的人数要尽量接近。多解的时候输出任意方案,无解时候输出No Solution。
思路
组的编号为0和1。因为同组的人必须相互认识,如果已知某个人在组0,那么不认识此人的就必须在组1。
让不认识关系组成一张图。
例如:
1 认识 2 3 5
2 认识 1 3 4 5
3 认识 1 2 5
4 认识 1 2 3
5 认识 1 2 3 4
那么不认识关系就是
2
4-1 4-3 4-5
代码
#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <vector>using namespace std;#define maxn 205int G[maxn][maxn];//原关系图vector<int> Ng[maxn];//不认识关系图vector<int> C[4];//将每一组染色的数目int color[maxn];//判断是否染色int diff_C[maxn];vector<int> list_color0[maxn];vector<int> list_color2[maxn];int CaseNum;int N;int dp[maxn][maxn*2];int cnt = 0;int cnt_color[3];//dfs过程,给点染色,并且bool dfs(int u,int father){ for(int i = 0 ; i<Ng[u].size(); i++) { int v = Ng[u][i]; if(v!=father) { if(color[v] == 0)//v没有染色 { color[v] = -color[u];//把与u相连的点v染色成相反的颜色 cnt_color[color[v]+1]++;//计数color[u]的点 if(color[v] + 1 == 0 ) list_color0[C[0].size()].push_back(v); if(color[v] + 1 == 2 ) list_color2[C[0].size()].push_back(v); if(!dfs(v,u)) return false; } else if(color[v] == -color[u]){//已经染色 但是颜色正确 } else//u已经染色 不存在这样的情况 return false; } } return true;}//输出结果void print_ans(int ans){ vector<int> team0,team2; for(int i = C[0].size()-1; i >= 0; i--) { int t = 0; if(dp[i][ans - diff_C[i] + N] == 1) { t = 0; ans -=diff_C[i]; } else { t = 1; ans += diff_C[i]; } if(t==1) { for(int j =0; j<list_color0[i].size(); j++) team0.push_back(list_color0[i][j]); for(int j =0; j<list_color2[i].size(); j++) team2.push_back(list_color2[i][j]); } else { for(int j =0; j<list_color0[i].size(); j++) team2.push_back(list_color0[i][j]); for(int j =0; j<list_color2[i].size(); j++) team0.push_back(list_color2[i][j]); } } printf("%d",team0.size()); for(int j=0; j<team0.size(); j++) printf(" %d",team0[j]); printf("\n"); printf("%d",team2.size()); for(int j=0; j<team2.size(); j++) printf(" %d",team2[j]); printf("\n");}int main(){ scanf("%d",&CaseNum); while(CaseNum--) { memset(G,0,sizeof(G)); scanf("%d",&N); for(int i =1; i<=N; i++) { int v; while(scanf("%d",&v)&&v) G[i][v] = 1; Ng[i].clear(); } //构成不认识关系图 for(int i = 1; i<=N; i++) { for(int j = i+1; j<=N; j++) { if((!G[i][j])||(!G[j][i])) { Ng[i].push_back(j); Ng[j].push_back(i); } } }/* for(int i = 1;i<=N;i++){ for(int j = 0; j<Ng[i].size();j++){ printf("%d %d\n",i,Ng[i][j]); } printf("\n"); }*/ // cnt = 0; cnt_color[0] = 0; cnt_color[2] = 0; C[0].clear(); C[1].clear(); for(int i = 0; i<N; i++) { list_color0[i].clear(); list_color2[i].clear(); } bool flag = true; for(int i =1 ; i<= N; i++) color[i] = 0; //置为没有染色 for(int i =1 ; i<= N; i++) { if(color[i] == 0) //若当前点没有染色 { color[i] = -1;//将color[i]染色为-1 cnt_color[-1+1]++;//颜色-1的总数++ list_color0[C[0].size()].push_back(i); flag = dfs(i,0); if(flag == false) break; C[0].push_back(cnt_color[0]); C[1].push_back(cnt_color[2]); //printf("%d %d %d\n",i,cnt_color[0],cnt_color[2]); cnt_color[0] = 0; cnt_color[2] = 0; } } if(flag == false) { printf("No solution\n"); if(CaseNum) cout<<endl; continue; } for(int i = 0; i< C[0].size(); i++) { //printf("%d %d\n",C[0][i],C[1][i]); diff_C[i] = C[0][i]-C[1][i]; }/* for(int i=0; i<C[0].size(); i++) { for(int j = 0; j< list_color0[i].size(); j++) { printf("color0 %d \n",list_color0[i][j]); } for(int j = 0; j< list_color2[i].size(); j++) { printf("color2 %d \n",list_color2[i][j]); } }*/ //使用dp算得每一组中的染色格子怎么放: memset(dp,0,sizeof(dp)); dp[0][0+N] = 1; for(int i = 0; i<C[0].size(); i++) { for(int j = -N; j<=N; j++) { if(dp[i][j+N]) { dp[i+1][j+diff_C[i] + N] = 1; dp[i+1][j-diff_C[i] + N] = 1; } } } for(int i = 0; i<=N; i++) { if(dp[C[0].size()][i+N]) { print_ans(i); break; } if(dp[C[0].size()][-i+N]) { print_ans(i); break; } } if(CaseNum) cout<<endl; } return 0;}
Hit
判断能否有解的时候,我出现了两个错误:
- 之前写的是如果下一个着色器已经有颜色,直接return false,这是个错误的写法,因为不认识关系是个四边形的环的时候,这种情况return false,但是其实是正确的。
- 还有一个dfs的地方写错,因为当下一个结点false的时候,其实整个dfs过程都是false。所以应该这样写:
if(!dfs(v,u)) return false;
阅读全文
0 0
- UVa1627
- uva1627
- (未解决)uva1627/poj1112
- poj 1112 uva1627
- uva1627(模型转换01背包)
- java基础问题
- Pocky HDU
- SSH原理与运用(一):远程登录
- Servlet的API和生命周期(二)
- Linux上LAMP服务器搭建
- uva1627
- 基于Django的微信公众号开发(4) -- 配置云数据库和本地测试库
- hihocoder 1636 Pangu and Stones
- mariadb
- js函数中两个比较有趣的方法:apply()和call()
- model和modelAttribute
- [14]_关于STM32的存储类型和启动方式、代码下载
- mac下idea的使用之代码调试debug篇
- SSH原理与运用(二):远程操作与端口转发