zoukankan      html  css  js  c++  java
  • 2008年NOI全国竞赛 假面舞会

    /*
    分三种情况
    1 有环:找环长的gcd作为max gcd的超过2的最小因子作为min
    2 树:所有最长链的和作为max 3为min (最长链≥3)
    3 两条相交链:找出所有的这样的两条链的差 同1求
    显然第三种不好处理 看了别人的做法是+反向-1的边 1 3就能合并了. 
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #define maxn 1000010
    #define pa pair<int,int>
    using namespace std;
    int n,m,num,head[maxn],dfn[maxn],topt;
    int c[maxn],sum,Gcd,ans,maxx,minn,x,y,d[maxn];
    bool f[maxn];
    struct node
    {
        int v,pre,t;
    }e[maxn],ei[maxn];
    int gcd(int a,int b)
    {
        return !b?a:gcd(b,a%b);
    }
    int abs(int a)
    {
        return a<0?-a:a;
    }
    void Add(int from,int to,int dis)
    {
        num++;e[num].v=to;
        e[num].t=dis;
        e[num].pre=head[from];
        head[from]=num;
    }
    void Tarjan(int x)
    {
        dfn[x]=++topt;f[x]=1;
        for(int i=head[x];i;i=e[i].pre)
          {
              int v=e[i].v;
              if(f[v]==0)d[v]=d[x]+e[i].t,Tarjan(v);
              else c[++sum]=abs(d[x]-d[v]+e[i].t);
          }
    }
    int Get_gcd()
    {
        Gcd=c[1];
        for(int i=2;i<=sum;i++)
          Gcd=gcd(Gcd,c[i]);
        return Gcd;
    }
    int Get_min()
    {
        int tmp=Gcd+1;
        for(int i=3;i<=Gcd;i++)
          if(Gcd%i==0)
            tmp=min(tmp,i);
        if(tmp==Gcd+1)tmp=-1;
        return tmp;
    }
    void Dfs(int x)
    {
        f[x]=1;
        for(int i=head[x];i;i=e[i].pre)
          {
              int v=e[i].v;
              if(f[v])continue;
              d[v]=d[x]+e[i].t;Dfs(v);
          }
        maxx=max(maxx,d[x]);
        minn=min(minn,d[x]);
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)
          scanf("%d%d",&x,&y),Add(x,y,1),Add(y,x,-1);
        for(int i=1;i<=n;i++)
          if(dfn[i]==0)Tarjan(i);
        Gcd=Get_gcd();ans=Get_min();
        if(Gcd)
          {
            if(Gcd<3)Gcd=ans=-1;
              printf("%d %d
    ",Gcd,ans);
            return 0;
          }
        ans=0;memset(f,0,sizeof(f));
        for(int i=1;i<=n;i++)
          if(f[i]==0)
            {
              maxx=0;minn=maxn;Dfs(i);
              ans+=maxx-minn+1;
            }
        if(ans>3)printf("%d 3
    ",ans);
        else printf("-1 -1
    ");
        return 0;
    }
  • 相关阅读:
    spring-cloud Feign
    spring-cloud eureka注册发现
    spring-cloud zuul网关
    正则表达式整理
    nginx配置-Rewrite
    nginx配置-main
    nginx用途
    Java命令行命令
    Task
    JavaScript难点整理
  • 原文地址:https://www.cnblogs.com/yanlifneg/p/5719564.html
Copyright © 2011-2022 走看看