【JZOJ6389】小w学图论
description
小w这学期选了门图论课,他在学习点着色的知识。他现在得到了一张无向图,并希望在这张图上使用最多n种颜色给每个节点染色,使得任意一条边关联的两个节点颜色不同。
小w获得一张n个节点m条边的基图,并得到了一份神秘代码。他会根据这份代码的内容构建完整的无向图。
while(1){
int modify_tag=0;
for(int x=1;x<=n;x++)
for(int y=x+1;y<=n;y++)
for(int z=y+1;z<=n;z++)
if(edge(x,y)∈G && edge(x,z)∈G){
add edge(y,z) to G
modify_tag=1;
}
if(modify_tag==0) break;
}
即对于图上的任意三元组x<y<z,若(x,y),(x,z)在图中则在图上加上一条(y,z)的边,直至无法加边为止。
小w想要知道使用n种颜色给这张基图生成的完整无向图的染色方案数。小w太菜了,他无力解决这个难题,于是只好把它交给了你。
analysis
首先有一个结论,\(ans=\prod n-g[i]\),\(g[i]\)表示与\(i\)相连、编号比\(i\)大的节点数量
如果从大到小染色染到第\(i\)位,\(g[i]\)已经染过色了且\(i\)点和这\(g[i]\)个点构成完全图
那么这\(g[i]\)个点颜色都不相同,\(i\)位染色的方案数就是\(n-g[i]\),以此类推
暴力做法是\(O(n^2)\)把这个图建出来,搞出每一个\(g[i]\),全部乘起来
其实可以考虑维护\(n\)棵线段树,存储第\(i\)位向后的连边情况
编号从小到大合并,假设合并到第\(k\)位,区间查询比\(k\)大有多少已经连边的点,乘进答案
然后再找出比\(k\)大且最小的存在的编号,把\(k\)的线段树合并到该编号的线段树就可以了
也可以用\(set\)维护连点的集合,合并两集合就启发式合并,但这个我还不是很懂
code
线段树合并
#pragma GCC optimize("O3")
#pragma G++ optimize("O3")
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define MAXN 100005
#define MAX MAXN*50
#define ha 998244353
#define ll long long
#define reg register ll
#define fo(i,a,b) for (reg i=a;i<=b;++i)
#define fd(i,a,b) for (reg i=a;i>=b;--i)
using namespace std;
ll root[MAXN],tr[MAX],mn[MAX],lson[MAX],rson[MAX];
ll n,m,tot,ans=1;
inline ll read()
{
ll x=0,f=1;char ch=getchar();
while (ch<'0' || '9'<ch){if (ch=='-')f=-1;ch=getchar();}
while ('0'<=ch && ch<='9')x=x*10+ch-'0',ch=getchar();
return x*f;
}
inline ll max(ll x,ll y){return x>y?x:y;}
inline ll min(ll x,ll y){return x<y?x:y;}
inline ll newnode()
{
++tot,mn[tot]=ha;
return tot;
}
inline void modify(ll &t,ll l,ll r,ll x)
{
if (!t)t=newnode();
++tr[t],mn[t]=min(mn[t],x);
if (l==r)return;
ll mid=(l+r)>>1;
if (x<=mid)modify(lson[t],l,mid,x);
else modify(rson[t],mid+1,r,x);
}
inline ll query_sum(ll t,ll l,ll r,ll x,ll y)
{
if (!t)return 0;
if (l==x && y==r)return tr[t];
ll mid=(l+r)>>1;
if (y<=mid)return query_sum(lson[t],l,mid,x,y);
else if (x>mid)return query_sum(rson[t],mid+1,r,x,y);
else return query_sum(lson[t],l,mid,x,mid)+query_sum(rson[t],mid+1,r,mid+1,y);
}
inline ll query_min(ll t,ll l,ll r,ll x,ll y)
{
if (!t)return ha;
if (l==x && y==r)return mn[t];
ll mid=(l+r)>>1;
if (y<=mid)return query_min(lson[t],l,mid,x,y);
else if (x>mid)return query_min(rson[t],mid+1,r,x,y);
else return min(query_min(lson[t],l,mid,x,mid),query_min(rson[t],mid+1,r,mid+1,y));
}
inline void merge(ll x,ll y,ll l,ll r)
{
if (l==r)return;ll mid=(l+r)>>1;
if (lson[x] && lson[y])merge(lson[x],lson[y],l,mid);
else if (lson[y])lson[x]=lson[y];
if (rson[x] && rson[y])merge(rson[x],rson[y],mid+1,r);
else if (rson[y])rson[x]=rson[y];
tr[x]=tr[lson[x]]+tr[rson[x]];
mn[x]=min(mn[lson[x]],mn[rson[x]]);
}
int main()
{
//freopen("T3.in","r",stdin);
freopen("graph.in","r",stdin);
freopen("graph.out","w",stdout);
n=read(),m=read();
fo(i,1,n)root[i]=newnode();
fo(i,1,m)
{
ll x=read(),y=read();
if (x>y)swap(x,y);
modify(root[x],1,n,y);
}
mn[0]=ha;
fo(i,1,n-1)
{
(ans*=n-query_sum(root[i],1,n,i+1,n))%=ha;
ll tmp=query_min(root[i],1,n,i+1,n);
if (tmp<=n)merge(root[tmp],root[i],1,n);
}
printf("%lld\n",ans*n%ha);
return 0;
}
set+启发式合并
#pragma GCC optimize("O3")
#pragma G++ optimize("O3")
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<set>
#define MAXN 100005
#define ha 998244353
#define ll long long
#define reg register ll
#define fo(i,a,b) for (reg i=a;i<=b;++i)
#define fd(i,a,b) for (reg i=a;i>=b;--i)
using namespace std;
set<ll>a[MAXN];
ll fa[MAXN];
ll n,m,ans=1,x,y;
inline ll read()
{
ll x=0,f=1;char ch=getchar();
while (ch<'0' || '9'<ch){if (ch=='-')f=-1;ch=getchar();}
while ('0'<=ch && ch<='9')x=x*10+ch-'0',ch=getchar();
return x*f;
}
int main()
{
//freopen("T3.in","r",stdin);
freopen("graph.in","r",stdin);
freopen("graph.out","w",stdout);
n=read(),m=read();
fo(i,1,n)fa[i]=i;
fo(i,1,m)x=read(),y=read(),a[min(x,y)].insert(max(x,y));
/*
fo(i,1,n)if (a[i].size())
{
printf("%lld\n",i);
for (set<ll>::iterator j=a[i].begin();j!=a[i].end();++j)printf("%lld ",*j);
printf("\n\n");
}
*/
fo(i,1,n)
{
//printf("!!!%lld:%lld\n",i,fa[i]);
//printf("%lld\n",*a[fa[i]].begin());
if (*a[fa[i]].begin()==i)a[fa[i]].erase(a[fa[i]].begin())/*,printf("#@!!#@!!$\n")*/;
(ans*=n-a[fa[i]].size())%=ha;
//printf("%lld %lld\n",i,n-a[fa[i]].size());
if (a[fa[i]].size()!=1)
{
ll &x=fa[i],&y=fa[*a[fa[i]].begin()];
if (a[x].size()>a[y].size())swap(x,y);
for (set<ll>::iterator tmp=a[x].begin();tmp!=a[x].end();++tmp)a[y].insert(*tmp);
a[x].clear();
}
//printf("\n");
//printf("!!!%lld:%lld\n",i,fa[i]);
}
//fo(i,1,n)printf("%lld:%lld ",i,fa[i]);
printf("%lld\n",ans);
return 0;
}
【JZOJ6389】小w学图论的更多相关文章
- 6389. 【NOIP2019模拟2019.10.26】小w学图论
题目描述 题解 之前做过一次 假设图建好了,设g[i]表示i->j(i<j)的个数 那么ans=∏(n-g[i]),因为连出去的必定会构成一个完全图,颜色互不相同 从n~1染色,点i的方案 ...
- UESTC_小panpan学图论 2015 UESTC Training for Graph Theory<Problem J>
J - 小panpan学图论 Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) S ...
- Day1T3小w的魔术扑克——图论
为什么不搞\(T2\)??? 因为我太菜了,那题我是真的搞不出来 题目描述 链接:https://ac.nowcoder.com/acm/contest/1100/C 来源:牛客网 小\(w\)喜欢打 ...
- 武汉科技大学ACM :1008: 小t和小w
Problem Description 小t最近学了C语言,他想要在女朋友小w面前展示一下自己的能力,小w喜欢如样例所示的图形, 想让小t写一个程序来输出这样的图形,小t拿到后感觉有点困难,小t不想在 ...
- 【牛客】小w的魔术扑克 (并查集?? 树状数组)
题目描述 小w喜欢打牌,某天小w与dogenya在一起玩扑克牌,这种扑克牌的面值都在1到n,原本扑克牌只有一面,而小w手中的扑克牌是双面的魔术扑克(正反两面均有数字,可以随时进行切换),小w这个人就准 ...
- 小w、小j和小z
n个月没更了,现在学的东西很难,掌握不好,不敢更! 这个题目既不超范围又足够难想,反正我没想出来,很好的题目! 我发现noi.ac上的题目很不错!!! ------------------------ ...
- XidianOJ 1076 小W喜欢的数字
题目描述 大家都知道,小W是一名大帅哥,当然比起Light还是有点儿差距的!帅气的小W认为0-9这些数字,只有1,3,5是完美的. 欲问小W为什么,小W总是说"帅哥,是不需要解释的" ...
- Swift语言 1小时速学教程
本文由 张渊杰 (网名寂静)编写 Swift语言 1小时速学教程 写在前面的话 有些人可能想, 呵呵, 1小时学一门语言, 你不是搞笑吧, 我想说, 是的, 完全可以, 就要看你怎么学了 要想在1小时 ...
- bzoj4665小w的喜糖 dp+容斥
4665: 小w的喜糖 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 120 Solved: 72[Submit][Status][Discuss] ...
随机推荐
- python调用tushare获取股票月线数据
接口:monthly 描述:获取A股月线数据 限量:单次最大3700,总量不限制 积分:用户需要至少300积分才可以调取,具体请参阅本文最下方积分获取办法 注:tushare库下载和初始化教程,请查阅 ...
- 41-Ubuntu-用户管理-06-su切换用户
su 切换用户 序号 命令 作用 说明 01 su - 用户名 切换用户,并且切换家目录 '-'可以切换到用户家目录,否则保持位置不变 02 exit 退出当前登录账户 返回上一级用户 图:su与ex ...
- android sdk 下载 最新版。。4.l
android sdk 下载 如今时间 2014.0709.,,这是最新的 64 位 windows 的 .为不能翻墙的小伙伴们准本
- JQuery on绑定click无效的的bug解决办法?
如果你在移动端使用zepto.js, touch 来代替click事件,那就没有上述标题的问题了.如果你仍然使用了click,在点击事件中苹果机就可能出现无效的结果. 第一种方法: 解决的方法很巧妙, ...
- ie兼容小知识点
1.ie的滤镜特别针对ie使用css3的使用 (1)从css3渐变:filter: progid:DXImageTransform.Microsoft.gradient(startcolorstr=# ...
- pandas-pd.read_csv
read_csv()接受以下常见参数: 参数 中文名 参数类型 默认参数 参数功能 说明 filepath_or_buffer various :文件路径.URL.或者 是read()函数返回的对 ...
- 深入研究js中的位运算及用法
什么是位运算? 位运算是在数字底层(即表示数字的 32 个数位)进行运算的.由于位运算是低级的运算操作,所以速度往往也是最快的(相对其它运算如加减乘除来说),并且借助位运算有时我们还能实现更简单的程序 ...
- 报错 DOMDocument not found
php -m 查看有没有dom扩展 没有安装扩展 yum install php-dom php 常用扩展有 yum install php-solr php-opcache php-seasLog ...
- 七牛云-C#SDK-上传-简单上传
请看系列C#-SDK-操作系列 https://i.cnblogs.com/posts?categoryid=1468598 接下来给大家分享的C#-SDK 简单上传 核心代码:有需要直接看这个,其实 ...
- 小程序生成海报:通过 json 配置方式轻松制作一张海报图
背景 由于我们无法将小程序直接分享到朋友圈,但分享到朋友圈的需求又很多,业界目前的做法是利用小程序的 Canvas 功能生成一张带有二维码的图片,然后引导用户下载图片到本地后再分享到朋友圈.而小程序 ...