CF228E 题解
CF228E 题解
题目简述
给定一个 个点, 条边的无向图,每条边都为 或 ,可以进行若干次操作,与此点相连的所有点权值取反,求一种方案使得所有边都变为 。
前置知识
- 二分图
- 二分图染色
思路简述
首先明白一点:对于同一条边,操作偶数次是没有必要的!因为最终会回到初始状态。
对于任意一条边 ,有:
若 ,则状态为 或 。
若 ,则状态为 或 。
然后我们就可以想到思路了。
用一个 color
数组来存储某个点 是没被染色(color[x]=-1
),还是染为黑或白色(color[x]
等于 或 )。
如果遇到某一条边,两个顶点颜色一样,则输出 Impossible
,无解。
否则统计某种颜色的顶点个数,再依次输出即可。
代码:
#include<bits/stdc++.h> using namespace std; const int N=105,M=N*(N-1)/2; int n,m,color[N],u,v,op,cnt_ans; struct E{ int from,to,pre,co; }e[M<<1]; int head[N],cnt_e; void add(int from,int to,int co) { e[++cnt_e].from=from; e[cnt_e].to=to; e[cnt_e].pre=head[from]; e[cnt_e].co=co; head[from]=cnt_e; return; } void dfs(int u,int co) { color[u]=co; for(int i=head[u];i;i=e[i].pre) { int v=e[i].to,col=e[i].co; if(!col) { if(color[v]==-1) dfs(v,co^1); else { if(color[v]==color[u]) { printf("Impossible\n"); exit(0); } } } else { if(color[v]==-1) dfs(v,co); else if(color[u]!=color[v]) printf("Impossible\n"),exit(0); } } return; } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) color[i]=-1; for(int i=1;i<=m;i++) { scanf("%d%d%d",&u,&v,&op); add(u,v,op); add(v,u,op); } for(int i=1;i<=n;i++) if(color[i]==-1) dfs(i,0); for(int i=1;i<=n;i++) if(!color[i]) ++cnt_ans; printf("%d\n",cnt_ans); for(int i=1;i<=n;i++) if(!color[i]) printf("%d ",i); puts(""); return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】