[BZOJ1064][Noi2008]假面舞会

试题描述

一年一度的假面舞会又开始了,栋栋也兴致勃勃的参加了今年的舞会。今年的面具都是主办方特别定制的。每个参加舞会的人都可以在入场时选择一 个自己喜欢的面具。每个面具都有一个编号,主办方会把此编号告诉拿该面具的人。为了使舞会更有神秘感,主办方把面具分为k (k≥3)类,并使用特殊的技术将每个面具的编号标在了面具上,只有戴第i 类面具的人才能看到戴第i+1 类面具的人的编号,戴第k 类面具的人能看到戴第1 类面具的人的编号。 参加舞会的人并不知道有多少类面具,但是栋栋对此却特别好奇,他想自己算出有多少类面具,于是他开始在人群中收集信息。 栋栋收集的信息都是戴第几号面具的人看到了第几号面具的编号。如戴第2号面具的人看到了第5 号面具的编号。栋栋自己也会看到一些编号,他也会根据自己的面具编号把信息补充进去。由于并不是每个人都能记住自己所看到的全部编号,因此,栋栋收集的信 息不能保证其完整性。现在请你计算,按照栋栋目前得到的信息,至多和至少有多少类面具。由于主办方已经声明了k≥3,所以你必须将这条信息也考虑进去。

输入

第一行包含两个整数n, m,用一个空格分隔,n 表示主办方总共准备了多少个面具,m 表示栋栋收集了多少条信息。接下来m 行,每行为两个用空格分开的整数a, b,表示戴第a 号面具的人看到了第b 号面具的编号。相同的数对a, b 在输入文件中可能出现多次。

输出

包含两个数,第一个数为最大可能的面具类数,第二个数为最小可能的面具类数。如果无法将所有的面具分为至少3 类,使得这些信息都满足,则认为栋栋收集的信息有错误,输出两个-1。

输入示例1


输出示例1

 

输入示例2


输出示例2

- -

数据规模及约定

100%的数据,满足n ≤ 100000, m ≤ 1000000。

题解

先看看我们知道什么。假设一个合法的答案是 k,则给了一条有向边(a, b)后,就说明 a 在第 i 组且 b 在第 i + 1 组,或者是 a 在第 k 组且 b 在第 1 组。

不难想到当给定的有向边形成一个环之后,k 一定是这个环长度的约数(因为它可以从第 1 组某个节点连到第 2 组某个节点,一直连到第 k 组某个节点,再从第 k 组的那个节点直接连一条边到第 1 组的某个节点,如此往复最终首尾相接,则这个环绕了若干圈这 k 个组)。

还有一种情况:a -> b -> c -> d -> e 且 a -> e,我们可以尝试给它分组,先考虑前面那条链,可以暂时将它们分成这个样子:a∈1,b∈2,c∈3,d∈4,e∈5,那么再加上 a -> e 这条边后发现 e 的编号应该等于 a 的编号加 1,所以将其与 b 分到第 2 组,同理 a 的编号应该等于原来 e 的编号减 1,所以将其与 d 分到第 4 组,最终结果是:b, e∈2,c∈3,a, d∈4,最终组数为 3。

综上两点可以得出一种做法:从每个连通分量的一个节点开始标号,顺着有向边走时标号加 1,逆着走时减 1,发现当前结点有标号时,则最大答案就是所有这种情况中的“原标号与新标号之差的绝对值”取最大公约数,最小答案就是所有所有这样的值取大于等于 3 的最小公约数。

注意一个特判,当给的图在以上两种情况之外,即将有向边变成无向边后没有圈的图(成为一个森林)时,每个连通分量的最大标号 - 最小标号 + 1,求和就是最大答案,最小答案是 3(若合法).

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <cstring>
#include <string>
#include <map>
#include <set>
using namespace std; const int BufferSize = 1 << 16;
char buffer[BufferSize], *Head, *Tail;
inline char Getchar() {
if(Head == Tail) {
int l = fread(buffer, 1, BufferSize, stdin);
Tail = (Head = buffer) + l;
}
return *Head++;
}
int read() {
int x = 0, f = 1; char c = Getchar();
while(!isdigit(c)){ if(c == '-') f = -1; c = Getchar(); }
while(isdigit(c)){ x = x * 10 + c - '0'; c = Getchar(); }
return x * f;
} #define maxn 100010
#define maxm 2000010
#define oo 2147483647
int n, m, head[maxn], next[maxm], to[maxm], dist[maxm], ans; void AddEdge(int a, int b) {
to[++m] = b; dist[m] = 1; next[m] = head[a]; head[a] = m;
swap(a, b);
to[++m] = b; dist[m] = -1; next[m] = head[a]; head[a] = m;
return ;
} int gcd(int a, int b) { return !b ? a : gcd(b, a % b); } int mark[maxn], mx, mn;
bool vis[maxn];
void dfs(int u, int x) {
if(vis[u]){ ans = gcd(ans, abs(mark[u] - x)); return ; }
vis[u] = 1; mark[u] = x; mx = max(mx, x); mn = min(mn, x);
for(int e = head[u]; e; e = next[e]) dfs(to[e], x + dist[e]);
return ;
} int main() {
n = read(); int m = read();
for(int i = 1; i <= m; i++) {
int a = read(), b = read();
AddEdge(a, b);
} int tmp = 0;
for(int i = 1; i <= n; i++) if(!vis[i]) {
mx = -oo; mn = oo;
dfs(i, 1);
tmp += mx - mn + 1;
}
int a2;
if(!ans) ans = tmp, a2 = 3;
else for(a2 = 3; a2 <= ans && ans % a2; a2++) ;
if(ans < 3) puts("-1 -1");
else printf("%d %d\n", ans, a2); return 0;
}

[BZOJ1064][Noi2008]假面舞会的更多相关文章

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

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

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

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

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

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

  4. BZOJ1064 NOI2008 假面舞会 图论

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

  5. BZOJ1064 NOI2008假面舞会

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

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

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

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

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

  8. NOI2008假面舞会

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

  9. 【洛谷】1477:[NOI2008]假面舞会【图论】

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

随机推荐

  1. impdp使用

    创建一个dir,dump_dir1,将备份文件放在下面 impdp szfetsc_card/123456 directory=dump_dir1 dumpfile=130912.dmp REMAP_ ...

  2. Scala 中的函数式编程基础(二)

    主要来自 Scala 语言发明人 Martin Odersky 教授的 Coursera 课程 <Functional Programming Principles in Scala>. ...

  3. ThinkPHP之视图模版的使用

    用户发起一个请求后,服务器应该返回一个页面,而页面是由我们的视图层来控制的. 一.修改控制器 <?php namespace Home\Controller; use Think\Control ...

  4. 每天一个linux命令(16):whereis 命令

    whereis命令只能用于程序名的搜索,而且只搜索二进制文件(参数-b).man说明文件(参数-m)和源代码文件(参数-s).如果省略参数,则返回所有信息. 和 find相比,whereis查找的速度 ...

  5. 【Matplotlib】 标注摄氏度符号

    之前论文中作图遇到的,其实也很简单. 关键的代码如下: ax.set_xlabel('Temperature ($^\circ$C)') 完整的样例代码如下: # -*- coding: utf-8 ...

  6. BZOJ-4195 NOI2015Day1T1 程序自动分析 并查集+离散化

    总的来说,这道题水的有点莫名奇妙,不过还好一次轻松A 4195: [Noi2015]程序自动分析 Time Limit: 10 Sec Memory Limit: 512 MB Submit: 836 ...

  7. 【codevs1409】 拦截导弹 2

    http://codevs.cn/problem/1409/ (题目链接) 题意 给出n个三维的导弹,每次拦截只能打x,y,z严格上升的若干个导弹,求最多能一次拦截下多少个导弹,以及最少拦截几次将所有 ...

  8. cogs896 圈奶牛

    描述 农夫约翰想要建造一个围栏用来围住他的奶牛,可是他资金匮乏.他建造的围栏必须包括他的奶牛喜欢吃草的所有地点.对于给出的这些地点的坐标,计算最短的能够围住这些点的围栏的长度. PROGRAM NAM ...

  9. MVC简介

    全名是Model View Controller,模型-视图-控制器,一种软件设计典范,用一种业务逻辑.数据.界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互 ...

  10. hdu acmsteps 2.1.8 Leftmost Digit

    Leftmost Digit Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Tota ...