1 条题解
-
0
自动搬运
来自洛谷,原作者为

FFTotoro
龙猫搬运于
2025-08-24 23:06:33,当前版本为作者最后更新于2024-11-26 19:33:35,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
如果每条边连接的两个点颜色都不相同,那么可以使用如下策略确定每个点的颜色:
令 为 到 的路径上的颜色数。对于每个点 ,以其为根进行一次 dfs,往下找直到找到一个和它颜色相同的或者一个叶子就回溯,如果遇到颜色相同的就将它们在并查集上合并。考虑如何在上面的过程中判断一个点 是否和它颜色相同:假设 到 的路径上除了 外离 最近的点为 (即 的某个儿子),只需要判断是否有 。
如果存在边连接的两个点颜色相同怎么办?考虑本质上可以把同样颜色的点构成的连通块“缩”成一个点(两个点 在同一个同色连通块里的充要条件为 ,可以用并查集维护)。显然最终构造出的树中这个同色连通块的形态是不重要的,所以可以用上面的每个连通块的“代表元”建树(可以证明在图上随便跑出一棵生成树都是对的),跑上一段所述的流程,之后把连通块中的其他点全部连到这个点上即可。
放代码:
#include<bits/stdc++.h> using namespace std; typedef pair<int,int> pii; namespace IAOI_lib{ template<typename T> class dsu{ private: vector<T> a; vector<int> s; public: dsu(int n=2e5){ a.resize(n),s.resize(n,1); iota(a.begin(),a.end(),0); } T leader(T x){ return a[x]==x?x:a[x]=leader(a[x]); } inline int size(T x){ return s[leader(x)]; } inline void merge(T x,T y){ x=leader(x),y=leader(y); if(x==y)return; if(s[x]>s[y])swap(x,y); s[y]+=s[x],a[x]=y; } inline bool same(T x,T y){ return leader(x)==leader(y); } }; // 并查集模板 } int main(){ ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int t,n; cin>>t>>n; vector a(n,vector<int>(n)); for(auto &i:a)for(auto &j:i)cin>>j; IAOI_lib::dsu<int> d(n),d1(n),d2(n); for(int i=0;i<n;i++) for(int j=i+1;j<n;j++) if(a[i][j]==1)d.merge(i,j); // 在一个同色连通块里 vector<vector<int> > g(n); vector<pii> e; for(int i=0;i<n;i++) if(i==d.leader(i)) for(int j=i+1;j<n;j++) if(j==d.leader(j)&&a[i][j]==2&&!d1.same(i,j)){ g[i].emplace_back(j); g[j].emplace_back(i); e.emplace_back(i,j),d1.merge(i,j); } // 用代表元建树 for(int i=0;i<n;i++) if(i!=d.leader(i)) e.emplace_back(i,d.leader(i)); // 把同色连通块内其他结点连向代表元 function<void(int,int,int,int)> dfs=[&](int u,int f,int r,int s){ if(~s&&a[r][u]==a[s][u]) d2.merge(r,u); // 颜色相同 else for(int i:g[u]) if(i!=f)dfs(i,u,r,s<0?i:s); }; // dfs 染色过程 for(int i=0;i<n;i++) if(i==d.leader(i))dfs(i,i,i,-1); for(int i=0;i<n;i++) cout<<d2.leader(d.leader(i))+1<<' '; cout<<endl; for(auto [u,v]:e) cout<<u+1<<' '<<v+1<<'\n'; return 0; }
- 1
信息
- ID
- 11014
- 时间
- 2000ms
- 内存
- 500MiB
- 难度
- 6
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者