题面

CF1444C Team-Building

给 \(n\) 个点 \(m\) 条边,每个点有颜色 \(c_i(1\le c_i\le k)\),求有多少个颜色对两组点并后是二分图。

数据范围:\(1\le n,m,k\le 5\cdot 10^5\)。


蒟蒻语

听人说是可撤销并查集后弃疗了,打出正解了没打完,其实普通并查集(权值并查集套权值并查集)就够了。

因为前面好多法师塔,只下了 \(7\) 分。


题解

看到判断二分图想到黑白染色。但是不想 dfs,怎么办?

有两种办法:拆点并查集和路径带权值并查集。蒟蒻选了后者。

对于一个颜色,内部不是二分图那么加入了另一组也不是二分图了。

所以可以先用路径带权值并查集在每个颜色内部把黑白关系连好,内部不是二分图的以后也不用管了。

然后处理两个颜色之间的。虽然看似 \(\Theta(n^2)\),但是如果两个颜色间没边必然是二分图,否则只有 \(\Theta(m)\) 个。

处理两个颜色间的,可以把两个颜色内部的每个连通块看作一个点,再套一层权值并查集然后连黑白关系。

外面那层并查集每次只需要初始化要用的就可以了,所以不需要可撤销。


代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
#define mp(a,b) make_pair((a),(b))
#define x first
#define y second
#define bg begin()
#define ed end()
#define sz(a) int((a).size())
#define pb(a) push_back(a)
#define R(i,a,b) for(int i=(a),i##E=(b);i<i##E;i++)
#define L(i,a,b) for(int i=(b)-1,i##E=(a)-1;i>i##E;i--)
const int iinf=0x3f3f3f3f;
const ll linf=0x3f3f3f3f3f3f3f3f; //Data
const int N=5e5;
int n,m,k,c[N],good;
bool bad[N]; //Graph
map<pair<int,int>,int> mp;
int mc; pair<int,int> me[N];
vector<pair<int,int>> e[N]; //Dsu
struct dsu{
int te[N],dep[N];
int find(int u){
if(te[u]==u) return u;
int an=find(te[u]);
dep[u]^=dep[te[u]];
return te[u]=an;
}
}d[2]; //Main
int main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n>>m>>k,good=k;
R(i,0,n) cin>>c[i],--c[i];
R(i,0,m){
int u,v; cin>>u>>v,--u,--v;
if(c[u]>c[v]) swap(u,v);
pair<int,int> t=mp(c[u],c[v]);
if(!mp.count(t)) mp[t]=mc,me[mc]=t,mc++;
e[mp[t]].pb(mp(u,v));
}
iota(d[0].te,d[0].te+n,0);
R(i,0,k)if(mp.count(mp(i,i))){
for(pair<int,int> t:e[mp[mp(i,i)]]){
int x=d[0].find(t.x),y=d[0].find(t.y);
if(x==y&&(d[0].dep[t.x]^d[0].dep[t.y]^1)!=0){bad[i]=true,good--;break;}
d[0].dep[x]=d[0].dep[t.x]^d[0].dep[t.y]^1,d[0].te[x]=y;
}
}
// cout<<"good="<<good<<'\n';
ll ans=1ll*good*(good-1)/2;
R(i,0,mc)if(me[i].x!=me[i].y){
if(bad[me[i].x]||bad[me[i].y]) continue;
for(pair<int,int> t:e[i]){
int xi=d[0].find(t.x),yi=d[0].find(t.y);
d[1].dep[xi]=0,d[1].te[xi]=xi,d[1].dep[yi]=0,d[1].te[yi]=yi;
}
for(pair<int,int> t:e[i]){
int xi=d[0].find(t.x),yi=d[0].find(t.y);
int x=d[1].find(xi),y=d[1].find(yi);
if(x==y&&(d[1].dep[xi]^d[0].dep[t.x]
^d[1].dep[yi]^d[0].dep[t.y]^1)!=0){ans--;break;}
d[1].dep[x]=d[1].dep[xi]^d[0].dep[t.x]
^d[1].dep[yi]^d[0].dep[t.y]^1,d[1].te[x]=y;
}
}
cout<<ans<<'\n';
return 0;
}

祝大家学习愉快!

题解-CF1444C Team-Building的更多相关文章

  1. BZOJ 4742: [Usaco2016 Dec]Team Building

    4742: [Usaco2016 Dec]Team Building Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 21  Solved: 16[Su ...

  2. CF1316E Team Building

    CF1316E [Team Building] 状压dp,感觉比D简单 \(f[i][s]\),表示考虑前\(i\)个人,状态为\(s\)(\(s\)的第\(j-1\)个二进制位表示队员的第\(j\) ...

  3. Spoj-BIPCSMR16 Team Building

    To make competitive programmers of BUBT, authority decide to take regular programming contest. To ma ...

  4. [题解] CF932E Team Work

    CF932E Team Work 你现在手里有\(n\)个人,你要选出若干个人来搞事情(不能不选),其中选择\(x\)个人出来的代价是\(x^k\),问所有方案的代价总和. 数据范围:\(1\le n ...

  5. BZOJ4742 : [Usaco2016 Dec]Team Building

    如果我们将两个人拥有的牛混在一起,并按照战斗力从小到大排序,同时把第一个人选的牛看成$)$,第二个人选的牛看成$($的话,那么我们会发现一个合法的方案对应了一个长度为$2k$的括号序列. 于是DP即可 ...

  6. 1742. Team building(dfs)

    1742 最小的是找联通块数 最大的找环 一个环算一个 其它的数各算一个 #include <iostream> #include<cstdio> #include<cs ...

  7. [USACO 2016Dec] Team Building

    [题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=4742 [算法] 动态规划 用Fi,j,k表示约翰的前i头牛和保罗的前j头牛匹配 , ...

  8. BZOJ练习记

    决定从头到尾干一波BZOJ!可能会写没几题就停下吧,但还是想学学新姿势啦. 1001. [BeiJing2006]狼抓兔子 即求 $(1, 1)$ 到 $(n, m)$ 的最小割.跑 dinic 即可 ...

  9. Codeforces 杂题集 2.0

      记录一些没有写在其他随笔中的 Codeforces 杂题, 以 Problemset 题号排序   1326D2 - Prefix-Suffix Palindrome (Hard version) ...

随机推荐

  1. Exactly Once 语义

    将服务器的 ACK 级别设置为-1,可以保证 Producer 到 Server 之间不会丢失数据,即 At Least Once 语义. 相对的,将服务器 ACK 级别设置为 0,可以保证生产者每条 ...

  2. (7)ASP.NET Core3.1 Ocelot Swagger

    1.前言 前端与后端的联系更多是通过API接口对接,API文档变成了前后端开发人员联系的纽带,开始变得越来越重要,而Swagger就是一款让你更好的书写规范API文档的框架.在Ocelot Swagg ...

  3. Python_用PyQt5 建 notepad 界面

    用PyQt5建notepad界面 1 # -*-coding:utf-8 -*- 2 """ 3 简介:用PyQt5做一个对话框,有菜单(2个.有独立图标.快捷键).提示 ...

  4. K尾相等数(模运算)

    Description 从键盘输入一个自然数K(K>1),若存在自然数M和N(M>N),使得K^M^和K^N^均大于或等于1000,且他们的末尾三位数相等,则称M和N是一对"K尾 ...

  5. Map结合Function函数式接口的巧妙之处

    需求:在给定 List 集合中,需根据不同的算法规则,选取计算方式并返回结果: 例如:[1, 2, 3, 4, 5] List 集合中都是 Integer 类型数据,根据提供的算法规则,sum 求和, ...

  6. 如何用Folx的浏览器集成功能设置捕获类型

    Folx的浏览器集成功能,可将Folx的下载功能添加到浏览器的上下文菜单(也就是右键快捷菜单)中,方便用户使用Folx捕获页面中的下载链接,并创建下载任务. 那么,用户需要进行哪些设置才能使用Folx ...

  7. 用OCR文字识别工具来审阅和处理PDF内容

    "工作的时候要同时打开好几个软件真的是太不方便了."很多公司白领都有这样的困扰.他们抱怨着进行文字识别过后又要打开文档编辑器来进行编辑.PDF是办公文档常用的格式, ABBYY F ...

  8. PHP 统计文件数和文件大小

    /** * 统计文件数和文件大小 */private function getFileCacheCount($pathName){ $data = [ 'num' => 0, 'size' =& ...

  9. 2020.6.16 night 解题报告

    2020.6.16 night 解题报告 link 标签(空格分隔): 题解 概率与期望 T1 : Crossing Rivers UVA - 12230 SB题. 很唬人的一个连续期望. 很明显,在 ...

  10. 2020 CSP-J 多校赛 Day 2 T2 题解

    0x01 引入 在考场时想了一个错误算法,口胡一下,或许对理解正解有点帮助. 我们考虑交换两个数产生的代价,你会发现我们需要让大的数重复被交换的次数尽可能少,减少它对后面的代价. 那么不难构思出一个按 ...