【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] ...
随机推荐
- java-day26
## DOM简单学习:为了满足案例要求 * 功能:控制html文档的内容 * 获取页面标签(元素)对象:Element * document.getElementByI ...
- vue-cli中进行微信支付代码详解
最近做微信支付,颇经历一番波折,这里总结一下,便于以后少走弯路: 在进行微信支付,除了需要公众号之外,你还需要一个微信商户.根据商户规则进行商户申请 这是公众号的基本开发配置,这里在微信授权的时候就已 ...
- c# mvc 简洁大气官网
后台管理 https://g.alicdn.com/idleFish-F2e/app-basic/item.html?itemid=580281597427&ut_sk=1.WCB2zfWM% ...
- Swift与OC混合开发
一.Swift调用OC 1. 创建{targetName}-Bridging-Header.h头文件,在BuildSetting -> bridging 2. Swift文件调用的OC中的类的头 ...
- utmp, wtmp - 登 录 记 录(login records)
SYNOPSIS[总览] #include DESCRIPTION[描述] utmp 文 件 用 于 记 录 当 前 系 统 用 户 是 哪 些 人. 但 是 实 际 的 人 数 可 能 比 这 个 ...
- Linux下Qt调用共享库文件.so
修改已有的pro文件,添加如下几句: INCLUDEPATH += /home/ubuntu/camera/camera/LIBS += -L/home/ubuntu/camera/camera -l ...
- HashMap和Hashtable有什么区别
HashMap和Hashtable都实现了Map接口,因此很多特性非常相似.但是,他们有以下不同点: HashMap允许键和值是null,而Hashtable不允许键或者值是null. Hashtab ...
- BCZM: Chapter 2
2.1 二进制数中 1 的个数 实现一个函数,输入一个无符号整数,输出该数二进制中的1的个数.例如把9表示成二进制是1001,有2位是1,因此如果输入9,该函数输出2 分析与解法 解法1:利用十进制和 ...
- Oracle使用——PLSQL的中文乱码显示全是问号--Oracle查询中文乱码
问题 这两天刚将PLSQL与Oracle配置好,可是在PLSQL中插入数据时,出现一个问题,PLSQL中的表里无法显示中文,中文无法保存.无法输出,中文在表中显示问号,如图: 原因 经过一番查证, ...
- HashSet 详解
基本介绍 1. 不允许重复(底层是HashMap,用key储存元素,value统一都是 PRESENT),可以为null,无顺序 2. HashSet就是为了提高查找效率的(在查找是否存在某个值时,A ...