BZOJ 1064 NOI 2008仮面舞踏会DFS
指定のn人、それぞれk種類の仮面をかぶって(k>=3、k未知)、その中でi種類の仮面をかぶっている人はi%k+1種類の人の仮面を見ることができて、いくつかの人の互いに見る関係を与えて、kの最大の最小値を求めます
問題を解く. http://www.cnblogs.com/proverbs/archive/2013/01/17/2865093.html
DFSリング長を求める
なお、図中にリングが存在しない場合のkの最大値は、すべての連通図における最長チェーンの長さの和である
正の辺の重みの値が+1の負の辺の重みの値が-1でGCDを計算する時絶対値を取ることに注意します
問題を解く. http://www.cnblogs.com/proverbs/archive/2013/01/17/2865093.html
DFSリング長を求める
なお、図中にリングが存在しない場合のkの最大値は、すべての連通図における最長チェーンの長さの和である
正の辺の重みの値が+1の負の辺の重みの値が-1でGCDを計算する時絶対値を取ることに注意します
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define M 100100
using namespace std;
struct abcd{
int to,f,next;
}table[1001001];
int head[M],f[M],tot=1;
int n,m,ansmax,ansmin,lmax,lmin;
bool v[M];
int GCD(int x,int y)
{
if(y==0) return x;
return GCD(y,x%y);
}
void dfs1(int x)
{
int i;
v[x]=1;
for(i=head[x];i;i=table[i].next)
{
if(!v[table[i].to])
f[table[i].to]=f[x]+table[i].f,dfs1(table[i].to);
else
ansmax=GCD(ansmax, abs(f[x]+table[i].f-f[table[i].to]) );
}
}
void dfs2(int x)
{
int i;
v[x]=1;
lmax=max(lmax,f[x]);
lmin=min(lmin,f[x]);
for(i=head[x];i;i=table[i].next)
if(!v[table[i].to])
{
f[table[i].to]=f[x]+table[i].f;
dfs2(table[i].to);
}
}
void add(int x,int y,int z)
{
table[++tot].to=y;
table[tot].f=z;
table[tot].next=head[x];
head[x]=tot;
}
int main()
{
freopen("party.in","r",stdin);
freopen("party.out","w",stdout);
int i,x,y;
cin>>n>>m;
for(i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
add(x,y,1);
add(y,x,-1);
}
for(i=1;i<=n;i++)
if(!v[i])
dfs1(i);
if(ansmax)
for(ansmin=3;ansmin<ansmax&&ansmax%ansmin;ansmin++);
else
{
memset(v,0,sizeof v);
memset(f,0,sizeof f);
for(i=1;i<=n;i++)
if(!v[i])
{
lmax=lmin=0;
dfs2(i);
ansmax+=lmax-lmin+1;
}
ansmin=3;
}
if(ansmax<3)
ansmax=ansmin=-1;
printf("%d %d
",ansmax,ansmin);
}