【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] ...
随机推荐
- 常用css3属性的ie兼容查看
记录一下关于css3的各种常用属性对ie各版本浏览器的兼容程度: 最低可兼容ie7 最低可兼容ie8 最低可兼容ie9 最低可兼容ie10 position:fixed clip E:first-le ...
- 在KVM虚拟化中如何实现vlan
换了好几个浏览器,都不能复制文字上来,不知道为什么.就发我的笔记截图吧
- 初识 SpringData - JPA(一)
概念 什么是 JPA JPA(Java Persistence API ): Java 持久化规范的 API .是 SUN 官方推出的一套基于 ORM 的规范,内部是由一系列的接口和抽象类构成.其提供 ...
- python数据读取路径为啥要用双反斜杠?
Window下python读取数据路径可以有三种表示方式: (1)'c:\\a.txt' ——>转义的方式.表示这里\\是一个普通\字符,不容易出错(2)r'c:\a.txt' ——>声明 ...
- 阿里云重磅推出物联网安全运营中心Link SOC
阿里云IoT自主研发了新一代物联网安全平台Link Security,面向IoT设备全生命周期构建了一整套全链路多层次的安全防御体系,IoT物联网平台的业务在不同层面可以按需集成安全能力. 1.首先在 ...
- PHP ftp_rawlist() 函数
定义和用法 ftp_rawlist() 函数返回 FTP 服务器上指定目录中文件的详细列表. 语法 ftp_rawlist(ftp_connection,dir,recursive) 参数 描述 ft ...
- struts之ActionServlet
ActionServlet类是Struts框架的内置核心控制器组件,它继承了javax. servlet.http.HttpServlet类,Struts的启动一般从加载ActionServlet开始 ...
- bzoj1009题解
[解题思路] 先KMP出fail数组,再用fail数组求出M[i][j],表示上一次匹配到第i位,这次可以遇到多少种不同的字符,使之转而匹配到第j位. 设集合S=[1,m]∩N 又设f[i][j]表示 ...
- bzoj_auto_submiter(辣鸡Py毁我青春系列)
听说你们的bzoj小号都很厉害? 不如试试bzoj金坷垃——bzoj_auto_submiter! 把所有的代码拖进解压后的文件夹,然后双击run.cmd. 看到有chrome浏览器窗口弹出来不要慌, ...
- 2019hdu第二场
10:签到求n!取模 #include <iostream> #include <iterator> #include <algorithm> typedef lo ...