• [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 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

    HINT

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

     

    solution

    分有无环两种情况考虑(简单环中几条边反连得到的伪环也是环):

      无环(链):易证无论k等于几都满足链上关系,所以maxans=所有连总长度,minans=3。

      有环:由于i类面具只能看到i+1类面具,所以对于每一个环,要满足条件,可都必须为环中面具种类数的约数,答案为公约数

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    using namespace std;
    int n,m,k,cnt,max_ans,min_ans;
    int fa[100005];
    int head[100005];
    bool vis[100005];
    bool used[100005];
    int dis[100005];
    int maxx[100005];
    int minn[100005];
    struct Edge{
        int fr;
        int to;
        int val;
        int nxt;
    }edge[2000005];
    void init(){
        memset(minn,0x3f,sizeof(minn));
        memset(maxx,-0x3f,sizeof(maxx));
        memset(head,-1,sizeof(head));
    }
    int findfa(int p){
        if(fa[p]==p)return p;
        return fa[p]=findfa(fa[p]);
    }
    void addedge(int f,int t,int v){
        cnt++;
        edge[cnt].fr=f;
        edge[cnt].to=t;
        edge[cnt].val=v;
        edge[cnt].nxt=head[f];
        head[f]=cnt;
    }
    int gcd(int a,int b){
        if(!b){
            return a;
        }
        return gcd(b,a%b);
    }
    void dfs(int u){
        maxx[k]=max(maxx[k],dis[u]);
        minn[k]=min(minn[k],dis[u]);
        vis[u]=true;
        for(int i=head[u];i!=-1;i=edge[i].nxt){
            int e=edge[i].to;
            if(!vis[e]){
                dis[e]=dis[u]+edge[i].val;
                dfs(e);
            }
            else max_ans=gcd(max_ans,abs(dis[u]+edge[i].val-dis[e]));
        }
    }
    int main(){
        init();
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            fa[i]=i;
        }
        for(int i=1;i<=m;i++){
            int u,v;
            scanf("%d%d",&u,&v);
            addedge(u,v,1);
            addedge(v,u,-1);
            int fs=findfa(u);
            int fv=findfa(v);
            if(fs!=fv)fa[fv]=fs;
        }
        for(int i=1;i<=n;i++){
            if(!vis[i]){
                k=findfa(i);
                dfs(i);
            }
        }
        if(!max_ans){
            for(int i=1;i<=n;i++){
                int fs=findfa(i);
                if(!used[fs]){
                    used[fs]=true;
                    max_ans+=maxx[fs]-minn[fs]+1;
                }
            }
            if(max_ans<3)max_ans=min_ans=-1;
            else min_ans=3;
        }
        else{
            if(max_ans<3)max_ans=min_ans=-1;
            else{
                for(int i=3;i<=max_ans;i++){
                    if(max_ans%i==0){
                        min_ans=i;
                        break;
                    }
                }
            }
        }
        printf("%d %d
    ",max_ans,min_ans);
        return 0;
    }
  • 相关阅读:
    忘记IBM服务器的登录IP
    分层思想
    防火墙的发展历史
    存储相关
    HCIE_交换篇_ARP欺骗
    堡垒机与网闸
    防止ARP欺骗
    信息安全等级保护
    DPM如何创建存储池?
    Lync2013的会话
  • 原文地址:https://www.cnblogs.com/lnxcj/p/9624308.html
Copyright © 2020-2023  润新知