AGC012D - Colorful Balls

Solution

连边题。
找出www最小的球yyy和www最小且颜色和yyy不同的球zzz。

  1. yyy向所有colt≠coly,wt+wy≤Ycol_t\not =col_y,w_t+w_y\leq Ycolt​​=coly​,wt​+wy​≤Y的球ttt连边。
  2. zzz向所有colt≠coly,wt+wz≤Ycol_t\not =col_y,w_t+w_z\leq Ycolt​​=coly​,wt​+wz​≤Y的球ttt连边。
  3. 每个球xxx和与自己颜色相同的www最小的球ttt连边,且需要满足wx+wt≤Xw_x+w_t\leq Xwx​+wt​≤X。

连边后连通块内部的点都可以任意交换位置。

且这样连边一定是合法的,并且包含了初始图所有可交换位置的信息。因为两个点交换如果要找中转点,选择www最小的显然不劣,那么把颜色相同的、颜色不同的最小点连边一定可以弄出所有的交换方案。

容易证明颜色数超过111的连通块至多有一个,且这个连通块包含yyy,答案只与这个连通块有关。设该连通块点数为numnumnum,各个颜色的球在该连通块中有cnt1,cnt2...cntkcnt_1,cnt_2...cnt_kcnt1​,cnt2​...cntk​个,则有:Ans=num!∏i=1kcnti!Ans=\frac{num!}{\prod\limits _{i=1}^k cnt_i!}Ans=i=1∏k​cnti​!num!​

于是用并查集维护连通块即可。

时间复杂度O(nlgn)O(nlgn)O(nlgn)。

Code

#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <ctime>
#include <cassert>
#include <string.h>
//#include <unordered_set>
//#include <unordered_map>
//#include <bits/stdc++.h>#define MP(A,B) make_pair(A,B)
#define PB(A) push_back(A)
#define SIZE(A) ((int)A.size())
#define LEN(A) ((int)A.length())
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define fi first
#define se secondusing namespace std;template<typename T>inline bool upmin(T &x,T y) { return y<x?x=y,1:0; }
template<typename T>inline bool upmax(T &x,T y) { return x<y?x=y,1:0; }typedef long long ll;
typedef unsigned long long ull;
typedef long double lod;
typedef pair<int,int> PR;
typedef vector<int> VI;const lod eps=1e-11;
const lod pi=acos(-1);
const int oo=1<<30;
const ll loo=1ll<<62;
const int mods=1e9+7;
const int MAXN=600005;
const int INF=0x3f3f3f3f;//1061109567
/*--------------------------------------------------------------------*/
inline int read()
{int f=1,x=0; char c=getchar();while (c<'0'||c>'9') { if (c=='-') f=-1; c=getchar(); }while (c>='0'&&c<='9') { x=(x<<3)+(x<<1)+(c^48); c=getchar(); }return x*f;
}
vector<int> V[MAXN];
int f[MAXN],col[MAXN],w[MAXN],cnt[MAXN],fac[MAXN],inv[MAXN];
int find(int x) { return f[x]==x?f[x]:f[x]=find(f[x]); }
int quick_pow(int x,int y)
{int ret=1;for (;y;y>>=1){if (y&1) ret=1ll*ret*x%mods;x=1ll*x*x%mods;}return ret;
}
void Init(int n)
{fac[0]=1;for (int i=1;i<=n;i++) fac[i]=1ll*fac[i-1]*i%mods;inv[n]=quick_pow(fac[n],mods-2);for (int i=n-1;i>=0;i--) inv[i]=1ll*inv[i+1]*(i+1)%mods;
}
signed main()
{int n=read(),X=read(),Y=read();Init(n);for (int i=1;i<=n;i++) col[i]=read(),w[i]=read(),V[col[i]].PB(i),f[i]=i;int id1=1,id2=0; w[0]=INF;for (int i=1;i<=n;i++) if (w[i]<w[id1]) id1=i;for (int i=1;i<=n;i++) if (col[i]!=col[id1]&&w[i]<w[id2]) id2=i;for (int i=1;i<=n;i++) if (col[i]!=col[id1]&&w[i]+w[id1]<=Y) f[find(i)]=find(id1);for (int i=1;i<=n;i++) if (col[i]!=col[id2]&&w[i]+w[id2]<=Y) f[find(i)]=find(id2);for (int i=1;i<=n;i++)if (V[i].size()){int id=V[i][0];for (auto v:V[i]) if (w[v]<w[id]) id=v;for (auto v:V[i]) if (w[v]+w[id]<=X) f[find(v)]=find(id);}int num=0;for (int i=1;i<=n;i++)if (find(f[i])==find(id1)) num++,cnt[col[i]]++;int ans=fac[num];for (int i=1;i<=n;i++)if (cnt[i]) ans=1ll*ans*inv[cnt[i]]%mods;printf("%d\n",ans);return 0;
}

AGC012D - Colorful Balls(并查集)相关推荐

  1. hdu-3635 Dragon Balls(并查集)

    题意: 初始化每个城市都有一个龙珠 进行两步操作 T  A  B 就是把A所在的城市的龙珠数都运到城市B中 Q  A   即要输出 A所在的城市 . A所在城市的个数.A移动的次数 本题貌似不需要把原 ...

  2. N - Dragon Balls(并查集+深度的意义

    有标号为1到n的n个龙珠,分别放在对应标号为1到n的n个城市里. 下面有两种操作: T A B表示把A龙珠所在城市的所有龙珠都转移到B龙珠所在的城市中 Q A 表示查询A,需要知道A龙珠现在所在的城市 ...

  3. hdu 3635 Dragon Balls 并查集应用记录每个点的转移次数

    题意: 有n个龙珠,分别存放在编号为1-n的城市里面.然后进行如下操作,T,a,b将a龙珠所在城市的所有龙珠都转移到b龙珠所在的城市,Q,a输出a龙珠所在的城市,以及该城市一共有多少个龙珠,同时输出该 ...

  4. hdu 3635 Dragon Balls 龙珠 带权并查集

    每次移动都是一个群龙珠移动到另一群龙珠所在的城市里面.所以这两个城市之间都不会空. 用并查集表示,每一个祖先节点的序号和他们所在城市的序号相同. 无论路径如何压缩,子结点的移动次数=父节点的移动次数+ ...

  5. hdu3635 Dragon Balls(带权并查集)

    /* 题意:有N个城市, 每一个城市都有一个龙珠(编号与城市的编号相同),有两个操作 T A ,B 将标号为A龙珠所在城市的所有的龙珠移动到B龙珠所在城市中!  思路:并查集 (压缩路径的时候将龙珠移 ...

  6. 【CF#505B】Mr. Kitayuta's Colorful Graph (并查集或Floyd或BFS)

    题干: Mr. Kitayuta has just bought an undirected graph consisting of n vertices and m edges. The verti ...

  7. hdu 3635 Dragon Balls(加权并查集)2010 ACM-ICPC Multi-University Training Contest(19)

    这道题说,在很久很久以前,有一个故事.故事的名字叫龙珠.后来,龙珠不知道出了什么问题,从7个变成了n个. 在悟空所在的国家里有n个城市,每个城市有1个龙珠,第i个城市有第i个龙珠. 然后,每经过一段时 ...

  8. AT2364 Colorful Balls

    AT2364 Colorful Balls 题意翻译 N个球排成一排,第i个球有颜色ci和重量wi. Snuke每次可以选择两个颜色相同,且重量之和不超过X的球,交换他们的位置. Snuke每次可以选 ...

  9. hdu 2473(并查集+删除操作)

    解题思路:这道题有并查集的删除操作,如果直接对这一棵树进行删除节点操作肯定是很困难的.所以可以建立虚拟节点,只要有一个节点要被删除,就直接把它投影到虚拟节点上,即用这个虚拟节点来代替我们要删除的节点. ...

最新文章

  1. Linux下查看系统信息
  2. Crypto++库在VS 2005中的使用——RSA加解密
  3. mysql字符串区分大小写么_mysql字符串区分大小写的问题-阿里云开发者社区
  4. python目录及文件_零基础小白必看:python基本操作-文件、目录及路径
  5. mysql多实例复制,Mysql实例使用Rotate Master实现MySQL 多主复制的实现方法
  6. linux nmap下载教程,Linux_在Linux系统上用nmap扫描SSL漏洞的方法,以下载nmap 6.45及以上版本。如 - phpStudy...
  7. python删除链表中的最小元素_LintCode Python 入门级题目 删除链表元素、整数列表排序...
  8. linux下配置Java和Go环境
  9. Windows10下python pip卸载并重新安装
  10. 0001-【linux系统】-用于生物信息分析该如何安装ubuntu系统?
  11. 扩展卡尔曼滤波soc估算 基于EKF算法的锂电池SOC
  12. C#调用百度大脑API初探2
  13. python提取数列数字_从pandas datafram中的列中提取字符串中的数字
  14. [置顶]生鲜配送管理系统_升鲜宝V2.0 销售订单汇总_采购任务分配功能_操作说明...
  15. SQL入门之第二一讲——IF函数的使用
  16. 智能可视化门铃方案调研报告
  17. 【小社交】谁是下一个陌陌?陌生人社交网络大起底!
  18. 计算机网络符号意思,浅析网络语言中的符号网语_计算机网络论文.doc
  19. 创业7堂课:看准路,选对人,找到钱
  20. Axure RP 新闻标题链接制作

热门文章

  1. 带你见识世界的5部纪录片(免费领取)
  2. 每次有人来家里,总有人问我这个积木在哪买的
  3. 进军人工智能,数学基础很重要?
  4. 免安装免配置 还免费的Spark 集群 --Databrickes Spark Clould
  5. 果园机器人是什么文体_果园机器人课文原文
  6. eeprom 数据偶尔变成ff_关于水电站冗余配置下监控系统下发调节令偶尔不动作的案例分析...
  7. mac mysql 移动硬盘_MAC一些高能过程记录(一些没必要的坑)
  8. 查询程序崩溃日志_PC 崩溃报告途径 amp; 临时解决方法
  9. python中matplotlib库实例_Python Matplotlib库入门指南
  10. silklabo哪个公众号有资源_微小说免费渣渣团资源公众号看大全集