zoukankan      html  css  js  c++  java
  • 假面舞会(codevs 1800)

    题目描述 Description

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

    输入描述 Input Description

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

    输出描述 Output Description

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

    样例输入 Sample Input

    【输入样例一】 
    6 5 1 2 2 3 3 4 4 1 3 5 
    【输入样例二】 
    3 3 1 2 2 1 2 3

    样例输出 Sample Output

    【输出样例一】 
    4 4 
    【输出样例二】 
    -1 -1

    数据范围及提示 Data Size & Hint

    50%的数据,满足 n ≤ 300, m ≤ 1000;

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

    /*
      首先明确思路:当出现环时,所有环长度的最大公约数即为ansmax,
      ansmin为ansmax的最小约数,没有环时,所有直链长度的和为ansmax,ansmin为3(ans>3) 
      做法:在建立变的同时,反向建立一条边权为-1的边。   我们要维护一个
                时间戳,记录第一次搜到某个点的时间,当再次搜到这个点时,
            深度-时间戳就是环长。
      解释:例如a->b->c->d,a->e->d,虽然没有出现环,但会重复搜到d,
              那么d的时间戳为3,此时“环长”为abs(2-3)=1。 
    */
    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #define N 100010
    #define M 1000010
    using namespace std;
    int head[N],dfn[N],vis[N],cnt,ansmax,ansmin,mx,mn;
    struct node
    {
        int v,t,pre;
    };node e[M];
    int gcd(int a,int b)
    {
        if(!b)return a;
        return gcd(b,a%b);
    }
    int read()
    {
        char c=getchar();int num=0;
        while(c<'0'||c>'9'){c=getchar();}
        while(c>='0'&&c<='9'){num=num*10+c-'0';c=getchar();}
        return num;
    }
    void add(int x,int y,int z)
    {
        e[++cnt].v=y;
        e[cnt].t=z;
        e[cnt].pre=head[x];
        head[x]=cnt;
    }
    void dfs1(int x)
    {
        vis[x]=1;
        for(int i=head[x];i;i=e[i].pre)
          if(!vis[e[i].v])
          {
            dfn[e[i].v]=dfn[x]+e[i].t;
            dfs1(e[i].v);
          }
          else ansmax=gcd(ansmax,abs(dfn[x]+e[i].t-dfn[e[i].v]));
    }
    void dfs2(int x)
    {
        vis[x]=1;
        mx=max(mx,dfn[x]);
        mn=min(mn,dfn[x]);
        for(int i=head[x];i;i=e[i].pre)
          if(!vis[e[i].v])
          {
              dfn[e[i].v]=dfn[x]+e[i].t;
              dfs2(e[i].v);
          }
    }
    int main()
    {
        int n=read(),m=read();
        for(int i=1;i<=m;i++)
        {
            int x=read(),y=read();
            add(x,y,1);add(y,x,-1);
        }
        for(int i=1;i<=n;i++)
          if(!vis[i])
            dfs1(i);
        if(ansmax)
          for(ansmin=3;ansmin<ansmax&&ansmax%ansmin;ansmin++);
        else
        {
            memset(dfn,0,sizeof(dfn));
            memset(vis,0,sizeof(vis));
            for(int i=1;i<=n;i++)
              if(!vis[i])
              {
                  mx=0;mn=0;
                  dfs2(i);
                  ansmax+=mx-mn+1;
              }
            ansmin=3;
        }
        if(ansmax<3)printf("-1 -1");
        else printf("%d %d",ansmax,ansmin);
        return 0;
    }
    View Code
     
  • 相关阅读:
    ASP.net:Literal控件用法
    css如何自动换行对于div,p等块级元素(转)
    java ftp操作类
    java文件操作类
    geoserver图层显示
    java csv读取
    geoserver 源码编译(转)
    ArcGIS Engine 空间运算
    ArcMap操作技巧
    geoserver开发资料收集
  • 原文地址:https://www.cnblogs.com/harden/p/5719507.html
Copyright © 2011-2022 走看看