# BZOJ1064 [Noi2008]假面舞会 【dfs】

6 5

1 2

2 3

3 4

4 1

3 5

4 4

## 提示

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

## 题解

#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long int
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define BUG(s,n) for (int i = 1; i <= (n); i++) cout<<s[i]<<' '; puts("");
using namespace std;
const int maxn = 100005,maxm = 2000005,INF = 1000000000;
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57) {if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57) {out = (out << 3) + (out << 1) + c - '0'; c = getchar();}
return out * flag;
}
int h[maxn],ne = 2;
struct EDGE{int to,nxt,w;}ed[maxm];
void build(int u,int v){
ed[ne] = (EDGE){v,h[u],1}; h[u] = ne++;
ed[ne] = (EDGE){u,h[v],-1}; h[v] = ne++;
}
int n,m,f[maxn],vis[maxn],pre[maxn],gmax[maxn],gmin[maxn],now;
int ansl,ansr;
int gcd(int a,int b){return b ? gcd(b,a % b) : a;}
int find(int u){return u == pre[u] ? u : pre[u] = find(pre[u]);}
void dfs(int u,int last){
gmax[now] = max(gmax[now],f[u]);
gmin[now] = min(gmin[now],f[u]);
vis[u] = true;
Redge(u) if ((k ^ 1) != last){
if (!vis[to = ed[k].to]) f[to] = f[u] + ed[k].w,dfs(to,k);
else {
ansr = gcd(abs(f[u] + ed[k].w - f[to]),ansr);
//printf("%d to %d\n",u,to);
}
}
}
int main(){
int a,b,fa,fb;
for (int i = 1; i <= n; i++) pre[i] = i;
while (m--){
build(a,b);
fa = find(a); fb = find(b);
if (fa != fb) pre[fb] = fa;
}
for (int i = 1; i <= n; i++) if (!vis[i]) now = find(i),dfs(i,0);
if (ansr){
for (int i = 3; i <= ansr; i++) if (ansr % i == 0){ansl = i; break;}
if (ansl < 3) puts("-1 -1");
else printf("%d %d\n",ansr,ansl);
}else {
for (int i = 1; i <= n; i++) if (find(i) == i) ansr += (gmax[i] - gmin[i] + 1);
if (ansr < 3) puts("-1 -1");
else printf("%d 3\n",ansr);
}
return 0;
}
posted @ 2018-03-03 13:37  Mychael  阅读(...)  评论(... 编辑 收藏