隐藏页面特效

CF662B Graph Coloring

很一眼的题

考虑枚举最后所有边的颜色,然后每个点是否变化可以用一个bool变量表示,就是个很典的2-SAT问题,根据当前边和目标的颜色相同与否连边即可

但这题的难点在于要找一个操作次数最少的方案,乍一看很难搞

但如果你对图论和2-SAT那一套理解比较深的话就很容易发现,这道题中所有边都是双向的

这就意味着当选择了某个点后,它所在的联通块的所有点都要被选,那么直接统计下每个联通块内要操作的次数,每次选较少的那边即可

算是个比较有意思的trick,可以mark一下

#include<cstdio> #include<iostream> #include<utility> #include<vector> #include<cstring> #include<cmath> #include<cstdlib> #include<algorithm> #include<queue> #include<set> #include<map> #include<set> #include<array> #include<random> #include<bitset> #include<ctime> #include<limits.h> #include<assert.h> #include<unordered_set> #include<unordered_map> #define RI register int #define CI const int& #define mp make_pair #define fi first #define se second #define Tp template <typename T> using namespace std; typedef long long LL; typedef long double LDB; typedef unsigned long long u64; typedef __int128 i128; typedef pair <int,int> pi; typedef vector <int> VI; typedef array <int,3> tri; const int N=200005; int n,m,x[N],y[N],c[N],dfn[N],low[N],stk[N],col[N],vis[N],ext[N],top,idx,scc; vector <int> v[N],id[N]; char ch[10]; inline void Tarjan(CI now) { dfn[now]=low[now]=++idx; stk[++top]=now; vis[now]=1; for (int to:v[now]) if (!dfn[to]) Tarjan(to),low[now]=min(low[now],low[to]); else if (vis[to]) low[now]=min(low[now],dfn[to]); if (low[now]==dfn[now]) { col[now]=++scc; vis[now]=0; if (now<=n) id[scc].push_back(now); while (stk[top]!=now) { col[stk[top]]=scc; if (stk[top]<=n) id[scc].push_back(stk[top]); vis[stk[top--]]=0; } --top; } } inline void addedge(CI x,CI y) { v[x].push_back(y); v[y].push_back(x); } inline vector <int> solve(CI tar) { RI i; for (i=1;i<=2*n;++i) v[i].clear(),id[i].clear(),dfn[i]=ext[i]=0; vector <int> ans; for (i=1;i<=m;++i) if (c[i]==tar) addedge(x[i],y[i]),addedge(x[i]+n,y[i]+n); else addedge(x[i],y[i]+n),addedge(x[i]+n,y[i]); for (idx=scc=0,i=1;i<=2*n;++i) if (!dfn[i]) Tarjan(i); for (i=1;i<=n;++i) if (col[i]==col[i+n]) return ans.resize(n),ans; for (i=1;i<=n;++i) { if (ext[col[i]]) continue; ext[col[i]]=ext[col[i+n]]=1; if (id[col[i]].size()<id[col[i+n]].size()) for (auto it:id[col[i]]) ans.push_back(it); else for (auto it:id[col[i+n]]) ans.push_back(it); } return ans; } inline void print(vector <int>& ans) { if (ans.size()==n) return (void)(puts("-1")); printf("%d\n",ans.size()); for (auto it:ans) printf("%d ",it); } int main() { //freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout); RI i; for (scanf("%d%d",&n,&m),i=1;i<=m;++i) scanf("%d%d%s",&x[i],&y[i],ch),c[i]=ch[0]=='B'; auto A1=solve(1),A2=solve(0); if (A1.size()<A2.size()) print(A1); else print(A2); return 0; }

__EOF__

本文作者hl666
本文链接https://www.cnblogs.com/cjjsb/p/17705768.html
关于博主:复活的ACM新生,目前爱好仅剩Gal/HBR/雀魂/单机/OSU
版权声明:转载请注明出处
声援博主:欢迎加QQ:2649020702来DD我
posted @   空気力学の詩  阅读(5)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
历史上的今天:
2020-09-15 AtCoder Grand Contest 028
点击右上角即可分享
微信分享提示