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

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1064

题意:一年一度的假面舞会又开始了,栋栋也 兴致勃勃的参加了今年的舞会。今年的面具都是主办方特别定制的。每个参加舞会的人都可以在入场时选择一 个自己喜欢的面具。每个面具都有一个编号,主办方会把此编号告诉拿该面具的人。为了使舞会更有神秘感,主办方把面具分为k (k≥3)类,并使用特殊的技术将每个面具的编号标在了面具上,只有戴第i 类面具的人才能看到戴第i+1 类面具的人的编号,戴第k 类面具的人能看到戴第1 类面具的人的编号。 参加舞会的人并不知道有多少类面具,但是栋栋对此却特别好奇,他想自己算出有多少类面具,于是他开始在人群中收集信息。 栋栋收集的信息都是戴第几号面具的人看到了第几号面具的编号。如戴第2号面具的人看到了第5 号面具的编号。栋栋自己也会看到一些编号,他也会根据自己的面具编号把信息补充进去。由于并不是每个人都能记住自己所看到的全部编号,因此,栋栋收集的信 息不能保证其完整性。现在请你计算,按照栋栋目前得到的信息,至多和至少有多少类面具。由于主办方已经声明了k≥3,所以你必须将这条信息也考虑进去。

思路:(1)首先我们假设给出的条件中存在环。那么所有环的长度的最大公约数G即为最多的面具种类;大于等于3且最小的且是G的约数的数即为最少的面具种类;G小于3时无解;

(2)假设不存在环,也就是都是一些有向链,那么所有连通块的最长链之和Sum就是最多的面具种类;3即为最少的面具种类。当然Sum<3时无解。

下面,就是如何求环和最长链。求环就是强连通分量,最长链可以从每个从每个入度为0的点向下计算一次(这里可以记录下从点u开始向下的最长链)。 建图时建成双向边,(x,y,1)和(y,x,-1)。(1)首先找环。我们从任意点开始DFS,每个点记录第一次被遍历时的距离。若下一个是一个已经遍 历过的点v,那么用当前的点u的d[u]更新后的点v的d为p,那么abs(p-d[v])就是环的长度;比如1-2-3-4-1这是环为4;但是对于 1-2-3-4,1-5-4,环的大小为1,得出无解(最后的最大公约数等于1);(2)找最长链。从某点开始DFS,这里记录边是否遍历,每条边及其反 向边只被遍历一次。并且这里也记录d值。这样每个连通分量的最大d值Max和最小d值Min :Max-Min+1就是该连通块的最长链长度。

struct node
{
    int v,w,next;
};

node edges[N<<2];
int head[N];
int e;

void Add(int u,int v,int w)
{
    edges[e].v=v;
    edges[e].w=w;
    edges[e].next=head[u];
    head[u]=e++;
}

int d[N];

int n,m,visit[N];

int Gcd(int x,int y)
{
    if(!y) return x;
    return Gcd(y,x%y);
}
int ans;

void DFS(int u)
{
    visit[u]=1;
    int i,v,w;
    for(i=head[u];i!=-1;i=edges[i].next)
    {
        v=edges[i].v;
        w=edges[i].w;
        if(visit[v])
        {
            ans=Gcd(ans,abs(d[u]+w-d[v]));
        }
        else
        {
            d[v]=d[u]+w;
            DFS(v);
        }
    }
}

int Max,Min;
int h[N];

void dfs(int u)
{
    visit[u]=1;
    Max=max(Max,d[u]);
    Min=min(Min,d[u]);
    int i,v,w;
    for(i=head[u];i!=-1;i=edges[i].next)
    {
        v=edges[i].v;
        w=edges[i].w;
        if(!h[i])
        {
            h[i]=h[i^1]=1;
            d[v]=d[u]+w;
            dfs(v);
        }
    }
}

int main()
{
    clr(head,-1);
    RD(n,m);
    int i,x,y;
    FOR1(i,m)
    {
        RD(x,y);
        Add(x,y,1);
        Add(y,x,-1);
    }
    FOR1(i,n) if(!visit[i]) DFS(i);
    if(ans)
    {
        for(i=3;i<=ans;i++) if(ans%i==0) break;
        if(ans<3) puts("-1 -1");
        else PR(ans,i);
        return 0;
    }
    clr(visit,0);
    int ans=0;
    FOR1(i,n) if(!visit[i])
    {
        Max=Min=d[i]=0;
        dfs(i);
        ans+=Max-Min+1;
    }
    if(ans<3) puts("-1 -1");
    else printf("%d %d\n",ans,3);
}

BZOJ 1064 假面舞会(图论-连通分量),布布扣,bubuko.com

时间: 2025-01-02 17:35:48

BZOJ 1064 假面舞会(图论-连通分量)的相关文章

BZOJ 1064 假面舞会

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

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

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

【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[NOI2008]假面舞会

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

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

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

【图论 搜索】bzoj1064: [Noi2008]假面舞会

做到最后发现还是读题比赛 Description 一年一度的假面舞会又开始了,栋栋也兴致勃勃的参加了今年的舞会.今年的面具都是主办方特别定制的.每个参加舞会的人都可以在入场时选择一 个自己喜欢的面具.每个面具都有一个编号,主办方会把此编号告诉拿该面具的人.为了使舞会更有神秘感,主办方把面具分为k (k≥3)类,并使用特殊的技术将每个面具的编号标在了面具上,只有戴第i 类面具的人才能看到戴第i+1 类面具的人的编号,戴第k 类面具的人能看到戴第1 类面具的人的编号. 参加舞会的人并不知道有多少类面

NOI2008假面舞会

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

[BZOJ1064][Noi2008]假面舞会

试题描述 一年一度的假面舞会又开始了,栋栋也兴致勃勃的参加了今年的舞会.今年的面具都是主办方特别定制的.每个参加舞会的人都可以在入场时选择一 个自己喜欢的面具.每个面具都有一个编号,主办方会把此编号告诉拿该面具的人.为了使舞会更有神秘感,主办方把面具分为k (k≥3)类,并使用特殊的技术将每个面具的编号标在了面具上,只有戴第i 类面具的人才能看到戴第i+1 类面具的人的编号,戴第k 类面具的人能看到戴第1 类面具的人的编号. 参加舞会的人并不知道有多少类面具,但是栋栋对此却特别好奇,他想自己算出

假面舞会(codevs 1800)

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