• BZOJ 1064 [Noi2008]假面舞会


    这题其实不是很难,就是我没写对。。

    把情况想全了:

    有很多个连通块(单向边看作双向边),对于每个连通块有这样几类情况:

    1、

    2、

    3、

    应该就是这几类吧~

    现在先讨论最大值

    第1类:对答案没有影响

    第2类:环上的点数一定是答案的倍数

    第3类:两个链的长度的差一定是答案的倍数

    所以答案就是2、3的最大公约数(有2、3存在的情况下)

    综上所述,先计算第1类,再就算2、3类。。

    ps:我是一起做的,然后长跪不起了,最后抄的lyd神犇的。。。

     有个技巧,就是把边权设为1和-1~

    View Code
      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 #include <cstdlib>
      6 #include <cmath>
      7 
      8 #define N 200000
      9 #define M 4000000
     10 
     11 using namespace std;
     12 
     13 int head[N],next[M],to[M],len[M];
     14 bool vis[N],bh[M];
     15 int d[N];
     16 int n,m,cnt,ans,tmax,tmin,an;
     17 
     18 inline void add(int u,int v,int w)
     19 {
     20     to[cnt]=v; len[cnt]=w; next[cnt]=head[u]; head[u]=cnt++;
     21 }
     22 
     23 inline void read()
     24 {
     25     memset(head,-1,sizeof head); cnt=0;
     26     scanf("%d%d",&n,&m);
     27     for(int i=1,a,b;i<=m;i++)
     28     {
     29         scanf("%d%d",&a,&b);
     30         add(a,b,1); add(b,a,-1);
     31     }
     32 }
     33 
     34 inline int gcd(int x,int y)
     35 {
     36     int ys;
     37     while(y)
     38     {
     39         ys=x%y;
     40         x=y; y=ys;
     41     }
     42     return x;
     43 }
     44 
     45 inline void dfs(int u)
     46 {
     47     vis[u]=true;
     48     for(int i=head[u];~i;i=next[i])
     49     {
     50         if(vis[to[i]])
     51         {
     52             ans=gcd(ans,abs(d[u]+len[i]-d[to[i]]));
     53         }
     54         else
     55         {
     56             d[to[i]]=d[u]+len[i];
     57             dfs(to[i]);
     58         }
     59     }
     60 }
     61 
     62 inline void tree(int u)
     63 {
     64     vis[u]=true;
     65     tmax=max(tmax,d[u]);
     66     tmin=min(tmin,d[u]);
     67     for(int i=head[u];~i;i=next[i])
     68         if(!vis[to[i]])
     69         {
     70             bh[i]=bh[i^1]=true;
     71             d[to[i]]=d[u]+len[i];
     72             tree(to[i]);
     73         }
     74 }
     75 
     76 inline void go()
     77 {
     78     for(int i=1;i<=n;i++)
     79         if(!vis[i]) dfs(i);
     80     if(ans)
     81     {
     82         for(an=3;an<ans&&ans%an;an++);
     83     }
     84     else
     85     {
     86         memset(vis,0,sizeof vis);
     87         for(int i=1;i<=n;i++)
     88             if(!vis[i])
     89             {
     90                 tmax=tmin=d[i]=0;
     91                 tree(i);
     92                 ans+=tmax-tmin+1;
     93             }
     94         an=3;
     95     }
     96     if(ans<3) ans=an=-1;
     97     printf("%d %d\n",ans,an);
     98 }
     99 
    100 int main()
    101 {
    102     read();go();
    103     return 0;
    104 }
  • 相关阅读:
    打卡规则小模块设计
    json和ajax学习
    求两个数的百分比&时间格式化&ajax返回json
    spring security运行流程图(转)
    DelegatingFilterProxy作用浅析
    网站URL重写(Java UrlRewrite 的使用)
    JVM的常用的调优策略和垃圾回收算法及Tomcat的常用调优参数
    JQuery 的Ajax的使用
    servlet程序HTTP Status 500
    CanvasRenderingContext2D.drawImage()无效,not working
  • 原文地址:https://www.cnblogs.com/proverbs/p/2865093.html
Copyright © 2020-2023  润新知