bzoj 1064

题意:戳这里

思路:很明显是一个图论模型。。

就两种图形:

1、图中存在环,那么就是所有环的gcd为最大答案。gcd的大于3的最小约数为最小答案

2、不存在环,那么是每个弱连通块的最长链之和为最大答案,最小答案为3。。

但是这一题最关键的是实现,实现技巧太赞了。。

首先,我们可以把每条有向边(u, v)拆成(u, v, 1), (v,  u, -1)

那么对于第二情况,对于每一个联通块直接随便找一个bfs,然后最长链就是maxdist-mindist+1

对于第一种情况,可能出现环套环的情况,这样处理起来很麻烦。。

但实际上很容易发现对于大环套小环实际上大环可以转换成大环-小环剩下的小圈求gcd。。注意这里的小圈不一定是环,因为边有正有负。。

这样正好处理可以一遍dfs处理。。

说得很抽象。。直接看这位神犇博客的图吧。。

code:

 1 #include <bits/stdc++.h>
 2 #define M0(a) memset(a, 0, sizeof(a))
 3 #define x first
 4 #define y second
 5 #define vii vector< pair<int, int> >::iterator
 6 using namespace std;
 7 const int maxn = 100010;
 8 vector< pair<int, int> > e[maxn];
 9 int n, m;
10
11
12 int vis[maxn], d[maxn];
13 void init(){
14      for (int i = 0; i <= n; ++i) e[i].clear();
15      int u, v;
16      pair<int, int> tmp;
17      for (int i = 0; i < m; ++i){
18           scanf("%d%d", &u, &v);
19           tmp.x = v, tmp.y = 1;
20           e[u].push_back(tmp);
21           tmp.x = u, tmp.y = -1;
22           e[v].push_back(tmp);
23      }
24 }
25
26 int ans;
27 void gao1(){
28      int ans1 = ans, ans2 = ans;
29      if (ans1 < 3){
30           puts("-1 -1"); return;
31      }
32      for (int j = 3; j <= ans; ++j) if (ans % j == 0){
33          ans2 = j; break;
34      }
35      printf("%d %d\n", ans1, ans2);
36 }
37
38
39 int bfs(const int s){
40     queue<int> q;
41     q.push(s), d[s] = 0, vis[s] = 1;
42     int u, v, w;
43     int maxdist= 0, mindist = 0;
44     while (!q.empty()){
45         u = q.front();
46         q.pop();
47         for (vii it = e[u].begin(); it != e[u].end(); ++it){
48               v = it->x, w = it->y;
49               if (vis[v]) continue;
50               d[v] = d[u] + w;
51               if (d[v] > maxdist) maxdist = d[v];
52               if (d[v] < mindist) mindist = d[v];
53               vis[v] = 1, q.push(v);
54         }
55     }
56     return maxdist - mindist + 1;
57 }
58
59 void gao2(){
60      M0(vis), M0(d);
61      int ans1 = 0;
62      for (int i = 1; i <= n; ++i) if (!vis[i])
63          ans1 += bfs(i);
64      if (ans1 < 3) puts("-1 -1");
65      else printf("%d %d\n", ans1, 3);
66 }
67
68 void dfs(int u){
69       vis[u] = 1;
70       int v;
71       for (vii it = e[u].begin(); it != e[u].end(); ++it){
72             v = it->x;
73             if (vis[v])
74                  ans = __gcd(ans, abs(d[u] + it->y - d[v]));
75             else
76                  d[v] = d[u] + it->y, dfs(v);
77       }
78 }
79
80 void solve(){
81      M0(vis), M0(d);
82      ans = 0;
83      for (int i = 1; i <= n; ++i) if (!vis[i])
84            dfs(i);
85      if (ans) gao1();
86      else gao2();
87 }
88
89 int main(){
90     freopen("a.in", "r", stdin);
91     while (scanf("%d%d", &n, &m) != EOF){
92          init();
93          solve();
94     }
95 }

时间: 2024-10-17 04:40:45

bzoj 1064的相关文章

BZOJ 1064 假面舞会(图论-连通分量)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1064 题意:一年一度的假面舞会又开始了,栋栋也 兴致勃勃的参加了今年的舞会.今年的面具都是主办方特别定制的.每个参加舞会的人都可以在入场时选择一 个自己喜欢的面具.每个面具都有一个编号,主办方会把此编号告诉拿该面具的人.为了使舞会更有神秘感,主办方把面具分为k (k≥3)类,并使用特殊的技术将每个面具的编号标在了面具上,只有戴第i 类面具的人才能看到戴第i+1 类面具的人的编号,戴第k

[bzoj 1064][NOI2008]假面舞会(dfs判断环)

题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1064 分析: 如果a看到b,则a->b 那么: 1.如果图中有环,则说明这个环的长度肯定是答案的倍数.所以最大种类数=所有环的长度的gcd,最小种类数=所有环的长度的公约数中>=3的最小数 2.如果图中没有环且都是单独的长链,那么最大种类数=每个联通图中最长链的和,最小种类数=3(如果没有则-1) 3.要考虑一种特殊情况:a->b->c->d a->e-&g

BZOJ 1064[NOI2008]假面舞会

1064: [Noi2008]假面舞会 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2044  Solved: 989[Submit][Status][Discuss] Description 一年一度的假面舞会又开始了,栋栋也兴致勃勃的参加了今年的舞会.今年的面具都是主办方特别定制的.每个参加舞会的人都可以在入场时选择一 个自己喜欢的面具.每个面具都有一个编号,主办方会把此编号告诉拿该面具的人.为了使舞会更有神秘感,主办方把面具分为k (k≥

bzoj 1064【noi2008】假面舞会

题意:http://www.lydsy.com/JudgeOnline/problem.php?id=1064 给一个有向图染色,每个点的后继必须相同,问至少&至多有多少种染色方案 sol:  图由多个联通块组成,对于每个联通块,考虑以下3种情况: 如果有环,分为3类讨论 对于第一种简单环,答案一定是环长的约数 对于第二种有反向边的环,答案一定是两条链长差的约数 trick:将有向边化为无向边,正向边权为1,反向为-1 这样1,2可以一起做 对于第三种大环套小环,将小环缩点即可(gcd(a,b)

【BZOJ 1064】 [Noi2008]假面舞会

1064: [Noi2008]假面舞会 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 988  Solved: 507 [Submit][Status] Description 一年一度的假面舞会又开始了,栋栋也兴致勃勃的参加了今年的舞会.今年的面具都是主办方特别定制的.每个参加舞会的人都可以在入场时选择一 个自己喜欢的面具.每个面具都有一个编号,主办方会把此编号告诉拿该面具的人.为了使舞会更有神秘感,主办方把面具分为k (k≥3)类,并使用特

BZOJ 1064 假面舞会

http://www.lydsy.com/JudgeOnline/problem.php?id=1064 思路:第一眼看的时候以为是差分约束,但是是做不了的,不过能保证的就是这题绝对是图论题...(废话) 分联通块考虑,如果每个联通块都是没有有向环的话,那么各个联通块中,最长链就是最大答案,3就是最小答案. 只要有一个联通块有环,那么答案一定是这个环长度的因数,最大答案,就是这些环长度的gcd 不过,要是有这个非正常的环怎么办? 我们可以看到,4->3和2->3都指向了3,这怎么办?那么我们只

bzoj 1064 noi2008 假面舞会题解

莫名其妙的变成了我们的noip互测题... 其实这题思想还是比较简单的,只是分类不好分而已 其实就是一个dfs的事 首先,非常明显,原题目中的所有关系可以抽象成一个图(这是...显而易见的吧...) 接下来,我们仅需在图上讨论即可 当然,这个图有几个部分组成其实并没有那么重要,毕竟,这些部分基本是互不干扰的. 所以接下来我们只需要对每一个块分别处理即可 我们来分类: 首先,如果所有块都是树,我们只需求出每个树上的最长链即可 接下来,如果存在环(包括真实的环和类环,即1-2-3-1和1-2-4+1

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

BZOJ 1064: [Noi2008]假面舞会 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1655  Solved: 798[Submit][Status][Discuss] Description 一年一度的假面舞会又开始了,栋栋也兴致勃勃的参加了今年的舞会.今年的面具都是主办方特别定制的.每个参加舞会的人都可以在入场时选择一 个自己喜欢的面具.每个面具都有一个编号,主办方会把此编号告诉拿该面具的人.为了使舞会更有神秘感,主办方把面具分为

【BZOJ】1064: [Noi2008]假面舞会(判环+gcd+特殊的技巧)

http://www.lydsy.com/JudgeOnline/problem.php?id=1064 表示想到某一种情况就不敢写下去了.... 就是找环的gcd...好可怕.. 于是膜拜了题解.. 和我想的差不多.. 首先发现这3几种情况: 1.一条或多条单链,那么最多有sum{单链长度}个面具,最少有3个面具 2.环.主要是大环套小环QAQ,显然我们只要小环就行了QAQ环的长度为标号差,gcd能满足这个性质,因此不管它.找出所有的环即可. 3.链相交.此时最大为相交链的长度差的gcd,最小