首页 > 其他分享 >洛谷 P11337 「COI 2019」IZLET 题解

洛谷 P11337 「COI 2019」IZLET 题解

时间:2024-12-19 20:43:48浏览次数:4  
标签:连通 洛谷 P11337 int 题解 return vector 颜色 leader

如果每条边连接的两个点颜色都不相同,那么可以使用如下策略确定每个点的颜色:

令 \(c_{i,j}\) 为 \(i\) 到 \(j\) 的路径上的颜色数。对于每个点 \(u\),以其为根进行一次 dfs,往下找直到找到一个和它颜色相同的或者一个叶子就回溯,如果遇到颜色相同的就将它们在并查集上合并。考虑如何在上面的过程中判断一个点 \(v\) 是否和它颜色相同:假设 \(u\) 到 \(v\) 的路径上除了 \(u\) 外离 \(u\) 最近的点为 \(s\)(即 \(u\) 的某个儿子),只需要判断是否有 \(c_{u,v}=c_{s,v}\)。

如果存在边连接的两个点颜色相同怎么办?考虑本质上可以把同样颜色的点构成的连通块“缩”成一个点(两个点 \(u,v\) 在同一个同色连通块里的充要条件为 \(c_{u,v}=1\),可以用并查集维护)。显然最终构造出的树中这个同色连通块的形态是不重要的,所以可以用上面的每个连通块的“代表元”建树(可以证明在图上随便跑出一棵生成树都是对的),跑上一段所述的流程,之后把连通块中的其他点全部连到这个点上即可。

放代码:

#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;
}

标签:连通,洛谷,P11337,int,题解,return,vector,颜色,leader
From: https://www.cnblogs.com/physics212303/p/18617888

相关文章

  • [Yandex Cup 2024 Qual F] Zeroth Rome 题解
    前言Englishversionofthiseditorialisprovidedafterthesamplecode.题意简述本题为交互题,你需要猜\(t\)个\([0,2024]\)间的非负整数\(x_1,x_2,\ldots,x_t\),可以询问最多\(15\)次,每次询问形如“给定一个大小为\(N(1\leN\le2025)\)的集合\(S\)满足\(S\)......
  • [APC001H] Generalized Insertion Sort 题解
    将\(a_i\)视为放在结点\(i\)上面的球;称位置\(i\)对应的球为\(i\),区别于“位置\(i\)上面的球为\(a_i\)”。考虑树是一条链的时候怎么做(下称链插入方法):此时只需要将这条链上面的球按照编号从上到下排序。这是一个类似插入排序的过程,维护深度最大的的若干个球编号的相对顺......
  • [USACO24OPEN] Grass Segments G 题解
    考虑对于一个区间\([l_i,r_i]\),最少重叠长度为\(k_i\),怎样的区间\([l_j,r_j]\)可以与前者产生贡献;首先\(r_j-l_j\gek_i\),在满足这个条件的情况下需要有\(r_j\gel_i+k_i\landl_j\ler_i-k_i\),这里\(\land\)表示合取,即C++中的\(\mathrm{and}\)。正难则反,考虑用长度\(......
  • 题解:P10483 小猫爬山
    思路第一眼我以为是个背包,但由于是分组,所以有多个缆车,明显不能用背包。我做这题是因为老师要求,那是我们在学深搜减枝,所以我就开始写深搜。这一题实际上是先选一直最重的猫,然后搞个\(sum\)数组,每搞一个新缆车的就下一个下标继续放,如果能放就放,当然也要搞一个能放但不放的。减枝......
  • 洛谷题单指南-线段树-Points
    原题链接:https://www.luogu.com.cn/problem/CF19D题意解读:坐标系支持集中操作:1.添加一个点(x,y),保证不会重复2.删除一个点(x,y)3.查询刚好比一个点(x,y)的x,y都大的点,优先看刚好比x大的位置,如果该位置有多个点,取y最小的一个,找到则输出点的坐标,找不到则输出-1。解题思路:首先,可......
  • RHCE环境公共问题解决(9.0)
    关于如何使用远程软件进行连接环境问题查看此处网络适配器模式,如果是NAT请修改为仅主机模式Vmware有两张网卡,一张是Vmware1,一张是Vmware8(环境必须用仅主机,避免环境判分错误)默认情况下,仅主机模式修改Vmware1网卡 打开Windows的网络适配器可以看到两张网卡 环境IP为1......
  • 洛谷Java写 P5727冰雹猜想
    题目再现:        给出一个正整数n,然后对这个数字一直进行下面的操作:如果这个数字是奇数,那么将其乘3 再加1,否则除以2。经过若干次循环后,最终都会回到11。经过验证很大的数字(7*10^11)都可以按照这样的方式比变成 11,所以被称为“冰雹猜想”。例如当n是20,变化的过程是......
  • AT_agc030_f [AGC030F] Permutation and Minimum 题解
    先去掉相邻两个都填完的位置,对于两个都没填的记个数为\(c\),最后只需要将答案乘上\(c!\)。接下来考虑从小到大枚举所有数进行dp,记\(f_{i,j,k}\)表示考虑完前\(1\simi\),有\(j\)个数需要跟一个位置确定的数匹配,有\(k\)个数需要跟后面一个自由的数匹配,考虑当前的数:如果......
  • AT_agc009_d [AGC009D] Uninity 题解
    一道妙妙题。一句话题意:求点分树的高度最小值。给所有点填上一个数表示它子树\(k\),考虑一种填法什么时候满足条件,发现当且仅当任意两对值相同的点之间的路径上存在一个权值更大的点。考虑随便找一个点作为根从叶子节点开始贪心填值,每次选择能填的最小值,发现这样填最终的值的最......
  • 洛谷P2756 飞行员配对方案问题
    题目洛谷P2756飞行员配对方案问题题目大意一共有n个飞行员前m个外籍飞行员,后(n-m)个则为英国飞行员一个外籍飞行员与英国飞行员进行匹配,求最大配合数思路不难看出本题考察匈牙利算法本体真正意思是给定一个二分图其左部点的个数为m右部点的个数为(n-m)求其最大匹配的边......