点此看题面

大致题意: 有\(k\)种面具(\(k\)是一个未知数且\(k≥3\),每种面具可能有多个),已知戴第\(i\)种面具的人能看到第\(i+1\)种面具上的编号,特殊的,戴第\(k\)种面具的人能看到第\(1\)种面具上的编号,现在用\(x\)和\(y\)来表示戴着第\(x\)号的面具的人能看到第\(y\)号面具的编号,给你\(m\)组\(x\)和\(y\)(信息可能并不完整),请你求出至多和至少有多少个面具。

题解

这道题可以近似地看作一个有向图,但是有向图在这道题目中是极难操作的,因此我们可以用一个简(xuan)单(xue)的小技巧:

add(x,y,1),add(y,x,-1);//将从x到y的有向边分成从x到y的权值为1的边和从y到x的权值为-1的边,虽说依然是有向图,但操作起来与无向图差不多,可以从两个方向走

有了这个铺垫,后面的过程就会省力许多。

其实,我们可以对这道题中的图进行一个分类讨论

第一种情况是图中只存在环

如果是个有向图,找环是个很麻烦的过程,但由于我们之前已经把这张图改成了无向图,找环就非常方便啦!

在找环的过程中,我们可以轻松计算出环的长度(用当前值减去上一次访问该节点时的值,然后取绝对值即可,具体实现见代码)。

此时,我们可以得出一个十分显然的结论:面具的种类数是所有环长的gcd的一个因数(证明?我也不知道,感性理解一下即可)。

因此,最终面具的种数的最大值应为所有环长的gcd,最小值应为该gcd大于等于3的最小因数

第二种情况则是图中不存在环,而是由若干棵树(这里我们把链也当作一棵树)组成。

这个时候的答案就更好推了,最大值就是最大的树的深度,最小值就是3,当然要注意判断最大值是否小于3,小于3要输出-1。

那不就好了吗?直接上代码!

等等。。。如果原图中既有环又有树(链)呢?那该怎么办?

答案是没关系!当作只有环来做就可以了,因为树在这种情况中可以忽略不计!

代码

#include<bits/stdc++.h>
#define N 100000
#define M 1000000
using namespace std;
int n,m,ans=0,ee=0,Min,Max,sum,lnk[N+5],vis[N+5],s[N+5];
struct edge
{
int to,nxt,val;
}e[2*M+5];
inline char tc()
{
static char ff[100000],*A=ff,*B=ff;
return A==B&&(B=(A=ff)+fread(ff,1,100000,stdin),A==B)?EOF:*A++;
}
inline void read(int &x)
{
x=0;int f=1;char ch;
while(!isdigit(ch=tc())) if(ch=='-') f=-1;
while(x=(x<<3)+(x<<1)+ch-'0',isdigit(ch=tc()));
x*=f;
}
inline void write(int x)
{
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10+'0');
}
inline void add(int x,int y,int z)
{
e[++ee].to=y,e[ee].nxt=lnk[x],e[ee].val=z,lnk[x]=ee;
}
inline int gcd(int x,int y)
{
return y?gcd(y,x%y):x;
}
inline void dfs(int x)//用dfs对原图进行遍历,记录是环长gcd和最大树的深度
{
vis[x]=1;//标记已访问
for(register int i=lnk[x];i;i=e[i].nxt)
{
if(vis[e[i].to]) ans=gcd(s[x]-s[e[i].to]+e[i].val,ans);//说明有环,并更新环长gcd
else s[e[i].to]=s[x]+e[i].val,Min=min(Min,s[e[i].to]),Max=max(Max,s[e[i].to]),dfs(e[i].to);//更新最大树的深度,并继续往下dfs
}
}
int main()
{
register int i;int x,y;
for(read(n),read(m),i=1;i<=m;++i)
read(x),read(y),add(x,y,1),add(y,x,-1);
for(i=1;i<=n;++i)
if(!vis[i]) Min=Max=0,dfs(i),sum+=Max-Min+1;//若当前节点没有访问过,则对其进行dfs
if(ans<0) ans=-ans;//ans在一波操作后可能会小于0,若其小于0则要将其改为正数
if(ans)//ans不为0说明有环
{
if(ans<3) return puts("-1 -1"),0;//ans小于3,说明无解,直接输出-1并退出程序
write(ans),putchar(' ');
for(i=3;i<=ans;i++)
if(!(ans%i)) return write(i),0;//寻找环长gcd大于3的最小因数
}
if(sum<3) puts("-1 -1");//判断最大深度是否小于3
else write(sum),putchar(' '),putchar('3');//输出答案
return 0;
}

【BZOJ1064】[NOI2008] 假面舞会(图上DFS)的更多相关文章

  1. [BZOJ1064][Noi2008]假面舞会

    [BZOJ1064][Noi2008]假面舞会 试题描述 一年一度的假面舞会又开始了,栋栋也兴致勃勃的参加了今年的舞会.今年的面具都是主办方特别定制的.每个参加舞会的人都可以在入场时选择一 个自己喜欢 ...

  2. 【做题记录】[NOI2008] 假面舞会—有向图上的环与最长链

    luogu 1477 [NOI2008] 假面舞会 容易发现: 如果图中没有环,那么面具种数一定是所有联通块内最长链之和,最少为 \(3\) . 如果有环,则面具种数一定是所有环的大小的最大公约数. ...

  3. BZOJ1064 [Noi2008]假面舞会 【dfs】

    题目 一年一度的假面舞会又开始了,栋栋也兴致勃勃的参加了今年的舞会.今年的面具都是主办方特别定制的.每个参加舞会的人都可以在入场时选择一 个自己喜欢的面具.每个面具都有一个编号,主办方会把此编号告诉拿 ...

  4. 【图论 搜索】bzoj1064: [Noi2008]假面舞会

    做到最后发现还是读题比赛:不过还是很好的图论题的 Description 一年一度的假面舞会又开始了,栋栋也兴致勃勃的参加了今年的舞会.今年的面具都是主办方特别定制的.每个参加舞会的人都可以在入场时选 ...

  5. BZOJ1064 NOI2008 假面舞会 图论

    传送门 将一组关系\((A,B)\)之间连一条边,那么显然如果图中存在环长为\(len\)的环,那么面具的种数一定是\(len\)的因数. 值得注意的是这里环的关系除了\(A \rightarrow ...

  6. BZOJ1064 NOI2008假面舞会(dfs树)

    将图中的环的长度定义为正向边数量-反向边数量,那么答案一定是所有环的环长的共同因子.dfs一下就能找到图中的一些环,并且图中的所有环的环长都可以由这些环长加加减减得到(好像不太会证).如果有环长为1或 ...

  7. BZOJ1064 NOI2008假面舞会

    挺神的这题,发现只有环和链两种情况 搜索时我们只考虑环的,因为链可以看成找不到分类的环. 当成链时大小是的最大值是各链长的和,最小值是3 当成环时最大值是各环长的gcd,最小值是大于3的最小的ans的 ...

  8. 【BZOJ1064】[Noi2008]假面舞会 DFS树

    [BZOJ1064][Noi2008]假面舞会 Description 一年一度的假面舞会又开始了,栋栋也兴致勃勃的参加了今年的舞会.今年的面具都是主办方特别定制的.每个参加舞会的人都可以在入场时选择 ...

  9. 图论 公约数 找环和链 BZOJ [NOI2008 假面舞会]

    BZOJ 1064: [Noi2008]假面舞会 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1655  Solved: 798[Submit][S ...

  10. NOI2008假面舞会

    1064: [Noi2008]假面舞会 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 883  Solved: 462[Submit][Status] ...

随机推荐

  1. Mysql-15-mysql分布式应用

    1.分布式应用的概念和优势 分布式数据库是指利用高速网络将物理上分散的多个数据存储单元连接起来组成一个逻辑上统一的数据库.分布式数据库的基本思想是将原来集中式数据库中的数据分散存储到多个通过网络连接的 ...

  2. JavaWeb:Servlet技术

    JavaWeb:Servlet技术 快速开始 Servlet是什么 Java Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 ...

  3. IDEA调试方法总结及各种Step的区别

    1.打断点 IDEA 添加断点的方式还是比较简单的,我们可以直接在某一行的代码行号后点击鼠标左键进行添加 2.启动调试 如果我们想要调试我们的程序,那我们必须以DEBUG的形式启动我们的程序,以DEB ...

  4. centos6.5下安装python3.6、pip、ipython

    一.先更换系统源 为了下载顺畅一般都会更改为国内源. 1 cd /etc/yum.repos.d/ 2 wget http://mirrors.163.com/.help/CentOS6-Base-1 ...

  5. 洛谷P1318 积水面积

    题目描述 一组正整数,分别表示由正方体叠起的柱子的高度.若某高度值为\(x\),表示由\(x\)个正立方的方块迭起(如下图,\(0<=x<=5000\)).找出所有可能积水的地方(图中蓝色 ...

  6. sql 查找重复数据,并且重复数据有子集

    SELECT A.* FROM comm_department A INNER JOIN ( select path,count(*) as count from comm_department gr ...

  7. 几种复杂度的斐波那契数列的Java实现

    一:斐波那契数列问题的起源 13世纪初期,意大利数论家Leonardo Fibonacci在他的著作Liber Abaci中提出了兔子的繁殖问题: 如果一开始有一对刚出生的兔子,兔子的长大需要一个月, ...

  8. varnish pipe 和pass的区别分析

    这两天在学习varnish,在学到vcl时,不理解pipe和pass的区别以及如何区分加以应用.通过两天的搜索,总算是理清了概念.现在记录在博客上跟大家分享. 当 vcl_recv 函数接收到请求时, ...

  9. [Environment Build] 工作中遇到的关于Git的问题

    修改已经提交的commit中的author, commit git commit --amend --author 'Your Name <Your Email>' git commit ...

  10. 【踩坑】遇到 org.apache.ibatis.binding.BindingException: Invalid bound statement (not found) 报错

    今天在重做 iblog 客户端时,测试接口情况,发现了 org.apache.ibatis.binding.BindingException: Invalid bound statement (not ...