zoukankan      html  css  js  c++  java
  • [NOI2008] 假面舞会

    18.09.09模拟赛T3。

    洛谷P1477 题目传送门

    bzoj1064 题目传送门

    本来以为是各种高深的图论算法,结果是dfs......

    大致讲一下思路:

    分为有环和无环两种情况。

    连边的时候,为了方便搜索,双向连边,正向连1,反向连-1。

    dfs时记录一个相对距离d。

    第一遍dfs找环,最大答案是所有环长的gcd。最小答案是gcd的一个因数。

    如果没有环,就进行第二次dfs。

    每一条链分别dfs,链长即为最大相对距离和最小相对距离的差。

    最大答案是所有链长之和,最小答案是3。

    注意如果ans<3,要特判为无解。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #define maxn 100010
     5 #define maxm 2000010
     6 using namespace std;
     7 
     8 int n,m;
     9 int hd[maxn],to[maxm],nx[maxm],val[maxm],ec=1;
    10 int v[maxn],d[maxn],ve[maxm];
    11 int ans,mxd,mnd;
    12 
    13 void edge(int af,int at,int kd)
    14 {
    15     to[++ec]=at;
    16     nx[ec]=hd[af];
    17     val[ec]=kd;
    18     hd[af]=ec;
    19 }
    20 
    21 int gcd(int x,int y)
    22 {
    23     return (!y)?x:gcd(y,x%y);
    24 }
    25 
    26 int abv(int x)
    27 {
    28     return (x>0)?x:(-x);
    29 }
    30 
    31 void o(int p)
    32 {
    33     v[p]=1;
    34     for(int i=hd[p];i;i=nx[i])
    35     {
    36         if(v[to[i]])ans=gcd(ans,abv(d[p]+val[i]-d[to[i]]));
    37         else d[to[i]]=d[p]+val[i],o(to[i]);
    38     }
    39 }
    40 
    41 void l(int p)
    42 {
    43     v[p]=1;
    44     mxd=max(mxd,d[p]);
    45     mnd=min(mnd,d[p]);
    46     for(int i=hd[p];i;i=nx[i])
    47     {
    48         if(ve[i])continue;
    49         ve[i]=ve[i^1]=1;
    50         d[to[i]]=d[p]+val[i];
    51         l(to[i]);
    52     }
    53 }
    54 
    55 int main()
    56 {
    57     scanf("%d%d",&n,&m);
    58     for(int i=1;i<=m;i++)
    59     {
    60         int ff,tt;
    61         scanf("%d%d",&ff,&tt);
    62         edge(ff,tt,1);
    63         edge(tt,ff,-1);
    64     }
    65     for(int i=1;i<=n;i++)if(!v[i])o(i);
    66     if(ans)
    67     {
    68         if(ans<3)
    69         {
    70             printf("-1 -1");
    71             return 0;
    72         }
    73         for(int i=3;i<=ans;i++)
    74         {
    75             if(ans%i)continue;
    76             printf("%d %d",ans,i);
    77             return 0;
    78         }
    79     }
    80     memset(v,0,sizeof(v));
    81     for(int i=1;i<=n;i++)
    82     {
    83         if(v[i])continue;
    84         mxd=mnd=d[i]=0;
    85         l(i);
    86         ans+=(mxd-mnd+1);
    87     }
    88     if(ans<3)printf("-1 -1");
    89     else printf("%d 3",ans);
    90     return 0;
    91 }
  • 相关阅读:
    手动安装ceph集群
    openstack端口禁用安全规则
    debian10桌面美化
    debian10 制作动态扩容根分区镜像
    CentOS7制作动态扩容根分区镜像
    EFKLK日志收集工具栈
    ceph rbd(csi) 对接 kubernetes sc
    secureCRT 814配色方案
    python function
    Linux操作篇之LNMP(一)
  • 原文地址:https://www.cnblogs.com/cervusy/p/9622994.html
Copyright © 2011-2022 走看看