BZOJ1064 NOI2008 假面舞会 图论
将一组关系\((A,B)\)之间连一条边,那么显然如果图中存在环长为\(len\)的环,那么面具的种数一定是\(len\)的因数。
值得注意的是这里环的关系除了\(A \rightarrow B \rightarrow C \rightarrow D \rightarrow A\)类型以外,\(A \rightarrow B \rightarrow C \rightarrow D + A \rightarrow D\)也是一种环,而后者的环长为\(3 - 1 = 2\),是两条路的路径之差。为了方便计算后面这种环,改变一下加边方式,对于一组关系\((A,B)\)从\(A\)向\(B\)连一条权值为\(1\)的边,从\(B\)往\(A\)连一条权值为\(-1\)的边,这样两种环都可以在图上表示出来。
找环的方法就是先抽出一棵DFS树,对于每一条非树边加进去出现的环计算贡献。
注意如果某一个环中存在\(\geq 2\)条非树边,可以不统计入答案:不妨证明有\(2\)条非树边的情况。设两条边是\(A \rightarrow B\)和\(C \rightarrow D\),DFS树根为\(E\),那么存在有两条非树边的环\(E \rightarrow D \rightarrow C \rightarrow B \rightarrow A \rightarrow E\),且同时存在\(E \rightarrow D \rightarrow C \rightarrow E\)和\(E \rightarrow B \rightarrow A \rightarrow E\)。经过\(2\)条非树边的环的权值正是后两条经过一条非树边的环的权值和,而\(gcd(a,b) = gcd(a , a+b) = gcd(b , a + b)\),所以在后两个环加入答案的情况下,\(E \rightarrow D \rightarrow C \rightarrow B \rightarrow A \rightarrow E\)在答案中没有意义的。
如果图中有环,那么最后的最大答案就是所有环长的\(gcd\),最小答案就是\(gcd\)因子中\(\geq 3\)的最小的那个。
如果图中没有环,因为可以连边把所有连通块连起来,那么最大答案就是所有连通块中的最长链的权值之和,最小答案就是\(3\)。
注意如果图中没有环而最长链权值之和\(\leq 3\)是要输出\(-1\ -1\)而不是\(3\ 3\)的
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<ctime>
#include<algorithm>
#include<cstring>
#include<iomanip>
#include<queue>
#define INF 0x3f3f3f3f
//This code is written by Itst
using namespace std;
inline int read(){
int a = 0;
char c = getchar();
while(!isdigit(c) && c != EOF)
c = getchar();
while(isdigit(c)){
a = a * 10 + c - 48;
c = getchar();
}
return a;
}
const int MAXN = 100007;
struct Edge{
int end , upEd , w;
}Ed[MAXN * 20];
int head[MAXN] , dis[MAXN] , N , M , cntEd , ans , minN , maxN , sum;
bool vis[MAXN];
inline int gcd(int a , int b){
if(!a || !b) return a + b;
a = a < 0 ? -a : a; b = b < 0 ? -b : b;
int r = a % b;
while(r){a = b; b = r; r = a % b;}
return b;
}
inline void addEd(int a , int b , int c){
Ed[++cntEd] = (Edge){b , head[a] , c};
head[a] = cntEd;
}
void dfs(int x){
minN = min(minN , dis[x]); maxN = max(maxN , dis[x]);
vis[x] = 1;
for(int i = head[x] ; i ; i = Ed[i].upEd)
if(!vis[Ed[i].end]){
dis[Ed[i].end] = dis[x] + Ed[i].w;
dfs(Ed[i].end);
}
else
ans = gcd(ans , dis[x] - dis[Ed[i].end] + Ed[i].w);
}
int main(){
#ifndef ONLINE_JUDGE
freopen("in","r",stdin);
//freopen("out","w",stdout);
#endif
N = read(); M = read();
for(int i = 1 ; i <= M ; ++i){
int a = read() , b = read();
addEd(a , b , 1); addEd(b , a , -1);
}
for(int i = 1 ; i <= N ; ++i)
if(!vis[i]){
minN = maxN = 0;
dfs(i);
sum += maxN - minN + 1;
}
if(!ans)
if(sum >= 3) cout << sum << " 3";
else cout << "-1 -1";
else if(ans <= 2) cout << "-1 -1";
else
for(int j = 3 ; j <= ans ; ++j)
if(ans % j == 0){
cout << ans << ' ' << j;
break;
}
return 0;
}
BZOJ1064 NOI2008 假面舞会 图论的更多相关文章
- [BZOJ1064][Noi2008]假面舞会
[BZOJ1064][Noi2008]假面舞会 试题描述 一年一度的假面舞会又开始了,栋栋也兴致勃勃的参加了今年的舞会.今年的面具都是主办方特别定制的.每个参加舞会的人都可以在入场时选择一 个自己喜欢 ...
- 【图论 搜索】bzoj1064: [Noi2008]假面舞会
做到最后发现还是读题比赛:不过还是很好的图论题的 Description 一年一度的假面舞会又开始了,栋栋也兴致勃勃的参加了今年的舞会.今年的面具都是主办方特别定制的.每个参加舞会的人都可以在入场时选 ...
- BZOJ1064 [Noi2008]假面舞会 【dfs】
题目 一年一度的假面舞会又开始了,栋栋也兴致勃勃的参加了今年的舞会.今年的面具都是主办方特别定制的.每个参加舞会的人都可以在入场时选择一 个自己喜欢的面具.每个面具都有一个编号,主办方会把此编号告诉拿 ...
- BZOJ1064 NOI2008假面舞会(dfs树)
将图中的环的长度定义为正向边数量-反向边数量,那么答案一定是所有环的环长的共同因子.dfs一下就能找到图中的一些环,并且图中的所有环的环长都可以由这些环长加加减减得到(好像不太会证).如果有环长为1或 ...
- BZOJ1064 NOI2008假面舞会
挺神的这题,发现只有环和链两种情况 搜索时我们只考虑环的,因为链可以看成找不到分类的环. 当成链时大小是的最大值是各链长的和,最小值是3 当成环时最大值是各环长的gcd,最小值是大于3的最小的ans的 ...
- 【BZOJ1064】[Noi2008]假面舞会 DFS树
[BZOJ1064][Noi2008]假面舞会 Description 一年一度的假面舞会又开始了,栋栋也兴致勃勃的参加了今年的舞会.今年的面具都是主办方特别定制的.每个参加舞会的人都可以在入场时选择 ...
- 图论 公约数 找环和链 BZOJ [NOI2008 假面舞会]
BZOJ 1064: [Noi2008]假面舞会 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1655 Solved: 798[Submit][S ...
- 【洛谷】1477:[NOI2008]假面舞会【图论】
P1477 [NOI2008]假面舞会 题目描述 一年一度的假面舞会又开始了,栋栋也兴致勃勃的参加了今年的舞会. 今年的面具都是主办方特别定制的.每个参加舞会的人都可以在入场时选择一 个自己喜欢的面具 ...
- NOI2008假面舞会
1064: [Noi2008]假面舞会 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 883 Solved: 462[Submit][Status] ...
随机推荐
- 「Android」单例的五种写法
单例 发现博客园可以很好的设置自己的博客文章的展示,很开心,然后特此发一篇 其实这几种写法大家应该都会的,就权当拿来记录一下吧,以后复习巩固也比较方便. 这篇文章中的代码,来自一篇视频(我想找视频贴上 ...
- AIDL基本使用
1.概述 Binder能干什么?Binder可以提供系统中任何程序都可以访问的全局服务.这个功能当然是任何系统都应该提供的,下面我们简单看一下Android的Binder的框架 Android Bin ...
- 生成器(generator,yield),next,send
#生成器 def generator(): for i in range(200): yield '哇哈哈%s' %i g = generator() #调用生成数函数,接受作用 ret = g.__ ...
- (jQuery插件)autocomplete插件的简单例子
1.引入相应的js和css,我用到的时候是在jquery-ui的js里面整合的,ui的css 2.先在html上写一个input <input id="tags" class ...
- centos开发环境安装的备忘
#Centos visudo运行普通用户$(whomai)执行sudo操作 http://www.cnblogs.com/xianyunhe/archive ...
- JMeter—常见问题(十四)
参考<全栈性能测试修炼宝典JMeter实战>第十五章 JMeter常见问题 1.无法产生负载 注意检查各元件是否时禁用状态.JMeter在运行时是以数形式加载各种元件的,如果父节点被禁用, ...
- Bcompare工具永久使用方法
bcompare的简介 我们在工作中会经常用到bcompare工具:合入驱动,对比原始文件等. bcompare,即Beyond Compare 是一个综合的比对工具. 可比对的对象包括纯文字档. ...
- vue v-nav指令属性列表
v-nav指令属性列表 属性名 属性描述 类型 必选 默认 title 导航栏标题 String No 空字符串 showBackButton 是否显示(左边的)返回按钮 Boolean No fal ...
- 《生命》第四集:Fish (鱼类)
旗鱼,是游动最快的鱼,他们不仅速度快,背上的鱼鳍还能吓唬成群的沙丁鱼,他们依靠速度与技巧结队捕食. 飞鱼,继续讲述了一下,飞鱼可以飞起来,把捕食者远远甩掉:飞鱼保护后代的方式是把卵产在水中的树叶上,很 ...
- CSS 浮动(float)与定位(position)
一.浮动 1.三个属性:left.right.none. 2.特点:容易造成父项塌陷,故在父项需要清除浮动 3.父项塌陷现象 4.父项塌陷解决方案(建议使用):清除浮动 .parent:after{ ...