[NOI2008]假面舞会

日常题目描述:

题目描述

一年一度的假面舞会又开始了,栋栋也兴致勃勃的参加了今年的舞会。

今年的面具都是主办方特别定制的。每个参加舞会的人都可以在入场时选择一 个自己喜欢的面具。每个面具都有一个编号,主办方会把此编号告诉拿该面具的人。

为了使舞会更有神秘感,主办方把面具分为k (k≥3)类,并使用特殊的技术将每个面具的编号标在了面具上,只有戴第i 类面具的人才能看到戴第i+1 类面具的人的编号,戴第k 类面具的人能看到戴第1 类面具的人的编号。

参加舞会的人并不知道有多少类面具,但是栋栋对此却特别好奇,他想自己算出有多少类面具,于是他开始在人群中收集信息。

栋栋收集的信息都是戴第几号面具的人看到了第几号面具的编号。如戴第2号面具的人看到了第5 号面具的编号。栋栋自己也会看到一些编号,他也会根据自己的面具编号把信息补充进去。

由于并不是每个人都能记住自己所看到的全部编号,因此,栋栋收集的信 息不能保证其完整性。现在请你计算,按照栋栋目前得到的信息,至多和至少有多少类面具。由于主办方已经声明了k≥3,所以你必须将这条信息也考虑进去。

本以为是tarjan判环,结果发现自己想复杂了。dfs即可。

代码:

#include<cmath>
#include<cstdio>
#include<algorithm>
using namespace std;
#define N 1000050
#define M 1000050
int n,m,hed[N],cnt=1;
struct Edge
{
    int to,nxt,vl;
}e[2*M];
void ae(int f,int t,int v)
{
    e[++cnt].to = t;
    e[cnt].nxt = hed[f];
    e[cnt].vl  = v;
    hed[f] = cnt;
}
int dis[N],ans;
bool vis[N];
int gcd(int a,int b)
{
    return b?gcd(b,a%b):a;
}
void dfs1(int u)
{
    vis[u] = 1;
    for(int j=hed[u];j;j=e[j].nxt)
    {
        int to = e[j].to;
        if(!vis[to])
        {
            dis[to] = dis[u]+e[j].vl;
            dfs1(to);
        }else
        {
            ans = gcd(ans,abs(dis[to]-dis[u]-e[j].vl));
        }
    }
}
int mn = 0x3f3f3f3f,mx = -0x3f3f3f3f;
bool vs2[M];
void dfs2(int u)
{
    vis[u] = 1;
    mn = min(dis[u],mn);
    mx = max(dis[u],mx);
    for(int j = hed[u];j;j = e[j].nxt)
    {
        int to = e[j].to;
        if(vs2[j])continue;
        vs2[j]=vs2[j^1]=1;
        dis[to] = dis[u]+e[j].vl;
        dfs2(to);
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int f,t,i=1;i<=m;i++)
    {
        scanf("%d%d",&f,&t);
        ae(f,t,1);ae(t,f,-1);
    }
    for(int i=1;i<=n;i++)if(!vis[i])dfs1(i);
    if(ans!=0)
    {
        if(ans<3)
        {
            printf("-1 -1
");
            return 0;
        }
        for(int i=3;i<=ans;i++)
        {
            if(ans%i==0)
            {
                printf("%d %d
",ans,i);
                return 0;
            }
        }
    }
    for(int i=1;i<=n;i++)dis[i]=0,vis[i]=0;
    for(int i=1;i<=n;i++)
    {
        if(!vis[i])
        {
            mn = mx = 0;
            dfs2(i);
            ans = ans+mx-mn+1;
        }
    }
    if(ans<3)
    {
        printf("-1 -1
");
        return 0;
    }
    printf("%d 3
",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/LiGuanlin1124/p/9621888.html