UVA1627 团队分组 Team them up! 题解
Solution
经典题。
考虑在同一个团队内的人互相是朋友关系,不妨转化一下:把不是朋友的人相互连边,那么此时同一个团队内的人互相之间则没有边。
考虑对建出来的图跑染色法,则我们会得到有数个二分图的图。考虑无解的情况:即在跑染色法时无解,则原图无解。
考虑共有
此时不妨设
不难推出状态转移方程:
-
,此时 ,表示选择了左半部分。 -
,此时 ,表示选择了右半部分。
最后利用辅助数组递归输出即可。
注意初始化以及建图用 vector
。同学实测用链式前向星会 TLE?
#include<bits/stdc++.h>
#define ll long long
#define x first
#define y second
#define il inline
#define debug() puts("-----")
using namespace std;
typedef pair<vector<int>,vector<int>> PII;
il int read(){
int x=0,f=1; char ch=getchar();
while(ch<'0'||ch>'9'){ if(ch=='-') f=-1; ch=getchar(); }
while(ch>='0'&&ch<='9') x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return x*f;
}
const int N=110;
int n;
bool flg;
int cnt=0;
PII vec[N];
int col[N];
int g[N][N];
bool f[N][N];
bool st[N][N];
vector<int> e[N];
vector<int> t1,t2;
il void dfs(int u,int w){
if(~col[u]){
if(col[u]!=w) flg=false;
return ;
} col[u]=w;
if(!w) vec[cnt].x.push_back(u);
else vec[cnt].y.push_back(u);
for(auto to:e[u]) dfs(to,w^1);
}
il void print(int i,int x){
if(!x) return ;
if(!g[i][x]){
for(auto u:vec[i].x) t1.push_back(u);
for(auto u:vec[i].y) t2.push_back(u);
print(i-1,x-vec[i].x.size());
} else{
for(auto u:vec[i].y) t1.push_back(u);
for(auto u:vec[i].x) t2.push_back(u);
print(i-1,x-vec[i].y.size());
}
}
il void solve(){
n=read();
cnt=0,flg=true;
t1.clear(),t2.clear();
for(int i=0;i<=n;i++)
for(int j=0;j<=n;j++)
f[i][j]=st[i][j]=false,g[i][j]=-1;
for(int i=1,x;i<=n;i++){
while(true){
x=read();
if(!x) break;
st[i][x]=true;
} col[i]=-1,e[i].clear();
vec[i].x.clear(),vec[i].y.clear();
} for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
if(!st[i][j]||!st[j][i]) e[i].push_back(j),e[j].push_back(i);
}
} for(int i=1;i<=n;i++) if(col[i]==-1) cnt++,dfs(i,0);
if(!flg){ puts("No solution\n"); return ; }
f[0][0]=true;
for(int i=1;i<=cnt;i++){
for(int j=0;j<=n;j++){
if(!f[i-1][j]) continue;
g[i][j+vec[i].x.size()]=0;
g[i][j+vec[i].y.size()]=1;
f[i][j+vec[i].x.size()]=true;
f[i][j+vec[i].y.size()]=true;
}
} int ans=n,res=0;
for(int i=1;i<=n;i++) if(f[cnt][i]&&abs(n-2*i)<ans) ans=abs(n-2*i),res=i;
print(cnt,res);
printf("%d ",(int)t1.size());
for(auto u:t1) printf("%d ",u); puts("");
printf("%d ",(int)t2.size());
for(auto u:t2) printf("%d ",u); puts("\n");
}
signed main(){
int T=read();
while(T--) solve();
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现