BZOJ1064【NOI2008】【假面舞会】

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

Input第一行包含两个整数n, m,用一个空格分隔,n 表示主办方总共准备了多少个面具,m 表示栋栋收集了多少条信息。接下来m 行,每行为两个用空格分开的整数a, b,表示戴第a 号面具的人看到了第b 号面具的编号。相同的数对a, b 在输入文件中可能出现多次。

Output包含两个数,第一个数为最大可能的面具类数,第二个数为最小可能的面具类数。如果无法将所有的面具分为至少3 类,使得这些信息都满足,则认为栋栋收集的信息有错误,输出两个-1。

Sample Input【输入样例一】

6 51 22 33 44 13 5

【输入样例二】

3 31 22 12 3Sample Output【输出样例一】4 4

【输出样例二】-1 -1HINT100%的数据,满足n ≤ 100000, m ≤ 1000000。这是一道比较水的图论题,想法很重要,细节问题要好好考虑。应为细节问题,硬生生磨了我一个下午才写出来。

每次读入的数据x,y,将x来拿一条有向正边给y,y连一条有向负边给x(为什么?之后会解释),这样答案转化成了求环的染色方案数的gcd(最大公约数),当只为一条链时,求链的最大长度。

链表比较好处理,所以先考虑环。

首先考虑一个简单环(就是N个点由N个路径连接起来的图),如下图两种染色方法,因为每个相同颜色的点的后驱颜色一定要相同,所以只有两种方案。所以可以证明一个简单环上的染色方案数为这个简单环的边数的约束(例如长度为4,有2,4两种方法)。

再考虑非简单环的类似环,这四个点构成了一种类似环的图,可以看出黄点到黑点的两种路径相反,两两相撞,红点到两个黄点有相同的路径,所以黄点红点黑点三个点都被确定了,联系上一幅图,是不是与第二种情况神似。所以我们在边上在建一条反向的负边,是我们可以继续走下去,并计算这幅图的贡献。可以看出加上负边后,等于黄点跨过了黑点,这种情况下,我们把这个有向图转换成无向图来看待,它还是一个简单环,此时合法的类数是环上正向边个数-反向边个数的约数。如下图是一个例子,这个“简单环”有6条正向边,2条反向边,注意到一条反向边肯定和一条正向边头碰头地“抵消”掉了,把这些边和点缩成一个点,这时候这个“简单环”就会变成一个普通的有向图的简单环,变成了上面的情况。扩展到一般情况,连续的若干条反向边和连续的若干条正向边也会像头碰头一样“抵消”掉。

图转化:

所以这样的环对答案的贡献为正向边减去反向边。求解则用bfs或dfs都行

请注意

  • 这道题可能有多个联通块,这样的话就不能只一次性求解,要加上枚举每个节点,判断是否已经计算过,没计算过的让该点为出发点开始计算

  • 不能直接走正反路,应该在遇到某个点访问第二次,用现在求出的路径长减去这个点本来就有的路径长

  • 求链时,开始的节点不一定是链的头,所以要将求出的最长长度减去最短长度(大部分时负数,因为走的是反向负边)得到链的长

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define maxn 100010
#define maxm 1000010
using namespace std;
int read(){    int x=0;char c=getchar();
    while(c<'0' || c>'9') c=getchar();
    while(c>='0' && c<='9')
        x=x*10+c-'0',c=getchar();
    return x;
}
struct w{    int id,v;
}pnt[maxm*2];
int ans;
int team[maxn*4],dis[maxn];
int head[maxn],nxt[2*maxm],cnt,sum;
int vis[maxn];
void add(int x,int y,int z){    nxt[++cnt]=head[x],head[x]=cnt;
    pnt[cnt]=(w){y,z};
}
int abs(int a){return a>0?a:-a;}
int gcd(int a,int b){    if(a<b) swap(a,b);
    if(a==0) return b;
    while(b){        int sub=a%b;
        a=b;
        b=sub;
    }
    return a;
}
void bfs(int s){    int h=0,t=1;
    team[1]=s;vis[s]=1,dis[s]=0;//dis[]保存到该节点的路径长,注意点2
    int MAX=0,MIN=0;//注意点3
    while(h<t){        int now=team[++h];
        for(int i=head[now];i!=-1;i=nxt[i]){            int to=pnt[i].id;
            if(!vis[to]){                dis[to]=dis[now]+pnt[i].v,team[++t]=to;
                MAX=max(MAX,dis[to]),MIN=min(MIN,dis[to]);
                vis[to]=1;
            }
            else{                ans=gcd(ans,abs(dis[now]+pnt[i].v-dis[to]));
            }
        }
    }
    sum+=MAX-MIN+1;
}
int main(){    freopen("1064.in","r",stdin);
    freopen("1064.out","w",stdout);
    memset(head,-1,sizeof(head));
    int n=read(),m=read();int s=1;
    for(int i=1;i<=m;i++){        int x=read(),y=read();
        add(x,y,1),add(y,x,-1);
    }
    ans=0;
    for(int i=1;i<=n;i++)
        if(!vis[i]) bfs(i);//注意点1
    if(!ans)
        if (sum>=3) return printf("%d %d",sum,3),0;
    for(int i=3;i<=ans;i++)
        if(!(ans%i)) return printf("%d %d",ans,i),0;
    puts("-1 -1");
    return 0;
}

乍一看好像代码不难,不长,其实还是有一定难度的,是一道图论好题!

BZOJ1064【NOI2008】【假面舞会】相关推荐

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

    做到最后发现还是读题比赛:不过还是很好的图论题的 Description 一年一度的假面舞会又开始了,栋栋也兴致勃勃的参加了今年的舞会.今年的面具都是主办方特别定制的.每个参加舞会的人都可以在入场时选 ...

  2. [bzoj1064][Noi2008]假面舞会

    题意:有n个人,每个人都有一个标号,每种标号的人只能看见下一个标号的人(最后一种标号看见第一种),给定m个关系,求这个关系是否合法以及合法情况下最大和最小的方案数.$n\leqslant 10^{5} ...

  3. BZOJ1064 NOI2008假面舞会

    挺神的这题,发现只有环和链两种情况 搜索时我们只考虑环的,因为链可以看成找不到分类的环. 当成链时大小是的最大值是各链长的和,最小值是3 当成环时最大值是各环长的gcd,最小值是大于3的最小的ans的 ...

  4. 【BZOJ1064】[Noi2008]假面舞会 DFS树

    [BZOJ1064][Noi2008]假面舞会 Description 一年一度的假面舞会又开始了,栋栋也兴致勃勃的参加了今年的舞会.今年的面具都是主办方特别定制的.每个参加舞会的人都可以在入场时选择 ...

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

    BZOJ 1064: [Noi2008]假面舞会 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 1655  Solved: 798 [Submit] ...

  6. 【做题记录】[NOI2008] 假面舞会—有向图上的环与最长链

    luogu 1477 [NOI2008] 假面舞会 容易发现: 如果图中没有环,那么面具种数一定是所有联通块内最长链之和,最少为 \(3\) . 如果有环,则面具种数一定是所有环的大小的最大公约数. ...

  7. bzoj 1064: [Noi2008]假面舞会(DFS)

    1064: [Noi2008]假面舞会 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 2240  Solved: 1083 [Submit][Sta ...

  8. [Noi2008]假面舞会(dfs判环)

    [Noi2008]假面舞会 Description 一年一度的假面舞会又开始了,栋栋也兴致勃勃的参加了今年的舞会.今年的面具都是主办方特别定制的.每个参加舞会的人都可以在入场时选择一 个自己喜欢的面具 ...

  9. [BZOJ]1064 [NOI2008] 假面舞会 dfs判环

    1064: [Noi2008]假面舞会 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 2160  Solved: 1047 [Submit][Sta ...

  10. 1064: [Noi2008]假面舞会

    1064: [Noi2008]假面舞会 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 1960  Solved: 941 [Submit][Stat ...

最新文章

  1. iOS学习之Runtime(二)
  2. sqlsever使用charindex查询中文字符返回固定值_10个MySQL使用技巧及30个搜索优化方法...
  3. 13、play中实现信息国际化
  4. ajax解析json中的对象数组对象,在JQuery中检索json数组后获取json对象Ajax
  5. arm linux dma_alloc_coherent 实现,dma_alloc_coherent (建立一致性 DMA 映射函数)
  6. wordpress linux伪静态,nginx下wordpress伪静态设置
  7. 给你出道题:依次去掉离中心最远的M个点
  8. 让PHP查询mysql时不区分大小写
  9. linux链接器脚本,vmlinux-lds 连接器脚本
  10. 求三角形面积(C++)
  11. 算法:单词匹配290. Word Pattern
  12. IMO FTPC Part 3-A、B和F级分隔耐火性能测试
  13. VBA实战技巧精粹之按某列相同数据分入同一个sheet
  14. html字体白色边框黑色效果,css完整总结:第二篇(尺寸,外补白,内补白,边框,背景,颜色,字体,文本,文本装饰)...
  15. Python分析双色球,中大奖指日可待
  16. android编辑按钮图标,修改 Floating Action Button 图标
  17. 分数在c语言程序中怎么输入,如何在c语言中实现分数相加,以分数形式输出,并化为最简...
  18. 一家披萨店不见客人,却能月入30万 !他们是怎么运营的呢?
  19. 秃头青年25岁躺平,30岁开始醒悟,还来得及奋斗吗
  20. Centos7安装播放器(mplayer vlc)

热门文章

  1. C和指针 第5章 操作符和表达式 5.1 操作符
  2. 小米面经(2021春招)
  3. 关于html5外文翻译三千字,论文外文文献翻译3000字左右.pdf
  4. my firefox常用的插件介绍
  5. javascript正则表达式-姜威-专题视频课程
  6. echarts画市县乡镇级地图
  7. H5 p,b,i,em,u,s标签
  8. 开机点用户名登录显示rfc服务器不可用,rpc服务器不可用怎么办(修复RPC服务器不可用方法)...
  9. web player html5源码,GitHub - WEBHH/DanmuPlayer: Html5弹幕视频播放器插件
  10. NDK开发(四):仿QQ变声