• BZOJ1064: [Noi2008]假面舞会 图论


    这个题很乱他的图首先是一个无向图我们在这里面找到无向环和有向环,用无向环的长度和有向环的长度差的gcd来更新答案,一个图一定可以由若干个简单环和边组成我们可以由dfs来找到这些,我们正向边为1反向边为-1把无向图变成有向图.

    如果这个图里没有这个限制那么他就一定是,一群橄榄,那么我们记录一下最长橄榄就好了,这个实质是找最长不同链,那么他肯定不会对之前的情况造成任何影响,因为有向环或无向环的贡献长度一定小于最大橄榄.

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #define N 100010
    #define M 1000010
    using namespace std;
    inline int abs(int x)
    {
       return x<0?0-x:x;
    }
    inline int read()
    {
        int sum=0;
        char ch=getchar();
        while(ch<'0'||ch>'9')ch=getchar();
        while(ch>='0'&&ch<='9')
        {
           sum=(sum<<1)+(sum<<3)+ch-'0';
           ch=getchar();
        }
        return sum;
    }
    struct Tr
    {
      int to,next,w;
    }c[M<<1];
    int n,m,head[N],t,ans,dis[N];
    bool visit[N],in[N];
    int Max,have,Min;
    inline void add(int x,int y,int z)
    {
       c[++t].to=y;
       c[t].next=head[x];
       head[x]=t;
       c[t].w=z;
    }
    inline void Init()
    {
       n=read(),m=read();
       for(int i=1;i<=m;i++)
       {
         int x=read(),y=read();
         add(x,y,1);
         add(y,x,-1);
       }
    }
    int gcd(int x,int y)
    {
       return x==0?y:gcd(y%x,x);
    }
    inline void get(int x)
    {
       if(!x)return;
       ans=gcd(ans,abs(x));
    }
    void dfs(int x,int now)
    {
       visit[x]=1;
       in[x]=1;
       dis[x]=now;
       if(now>Max)
        Max=now;
       if(now<Min)
        Min=now;
       for(int i=head[x];i;i=c[i].next)
           if(visit[c[i].to])
               {
                 if(in[c[i].to])
                   get(now+c[i].w-dis[c[i].to]);
               }
           else 
               dfs(c[i].to,now+c[i].w);
       in[x]=0;
    }
    inline void work()
    {
       for(int i=1;i<=n;i++)
        if(!visit[i])
        {
         Max=-0x3f3f3f3f;
         Min=0x7f7f7f7f;
         dfs(i,0);
         have+=Max-Min+1;
        }
    }
    inline void print()
    {
       if(!ans)
       {
          
          if(have<3)
           printf("-1 -1");
          else 
           printf("%d 3",have);
       }
       else
       {
          if(ans<3)
           printf("-1 -1");
          else
          {
            int Ans=ans;
            for(int i=3;i<ans;i++)
             if(ans%i==0)
             {
                Ans=i;
                break;
             }
            printf("%d %d",ans,Ans);
          }
       }
    }
    int main()
    {
       Init();
       work();
       print();
       return 0;
    }
  • 相关阅读:
    把我给另外一个朋友的炒股劝告发给你一遍,希望你可以得到帮助!
    Microsoft Office Document Imaging批量ocr 方法
    Advanced GET 9.1 修正汉化版(免注册、页面加载、保存都正常)
    波浪分析数据转换:大智慧、钱龙、胜龙可用Advanced GET ToGet 数据转换器V3.05特别版
    怎样精确计算股市主力的持仓量
    混沌理论
    地产联盟内部资料总目录
    C语言 · P1001(大数乘法)
    C语言 · 排列数
    C语言 · 逆序排列
  • 原文地址:https://www.cnblogs.com/TSHugh/p/7153759.html
Copyright © 2020-2023  润新知