• BZOJ 1064 假面舞会


    http://www.lydsy.com/JudgeOnline/problem.php?id=1064

    思路:第一眼看的时候以为是差分约束,但是是做不了的,不过能保证的就是这题绝对是图论题。。。(废话)

    分联通块考虑,如果每个联通块都是没有有向环的话,那么各个联通块中,最长链就是最大答案,3就是最小答案。

    只要有一个联通块有环,那么答案一定是这个环长度的因数,最大答案,就是这些环长度的gcd

    不过,要是有这个非正常的环怎么办?

    我们可以看到,4->3和2->3都指向了3,这怎么办?那么我们只要在一开始建图的时候,原来的有向边权值为1,再同时建一个反向边权值为-1,把有向图变成无向图。

    为什么?,因为如图,4可以到3,2也可以到3,说明2的编号和4相同,所以2->3->4的路径实际上是"走出去一步,又走回来一步",也就是我常说的"有来有回",按照我们刚才的建图方式,这个环的长度就是:1+1+1+1-1=3,事实上,答案也是如此,3和5编号相同,2和4编号相同,这样图中实际上是只有3种面具。

     1 #include<algorithm>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<cstring>
     5 #include<iostream>
     6 int tot,go[2100005],next[2100005],first[2100005];
     7 int c[200005],dis[200005],vis[200005],n,m,len,val[2100005];
     8 int read(){
     9     int t=0,f=1;char ch=getchar();
    10     while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
    11     while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();}
    12     return t*f;
    13 }
    14 void insert(int x,int y,int z){
    15     tot++;
    16     go[tot]=y;
    17     next[tot]=first[x];
    18     first[x]=tot;
    19     val[tot]=z;
    20 }
    21 void add(int x,int y){
    22     insert(x,y,1);insert(y,x,-1);
    23 }
    24 int gcd(int a,int b){
    25     if (b==0) return a;
    26     else return gcd(b,a%b);
    27 }
    28 int bfs(int x){
    29     int h=1,t=1;c[1]=x;vis[x]=1;dis[x]=0;
    30     int mxdis=0,mndis=0;
    31     while (h<=t){
    32         int now=c[h++];
    33         for (int i=first[now];i;i=next[i]){
    34             int pur=go[i];
    35             if (vis[pur]){
    36                 len=gcd(len,val[i]+dis[now]-dis[pur]);
    37                 continue;
    38             }
    39             vis[pur]=1;
    40             c[++t]=pur;
    41             dis[pur]=dis[now]+val[i];
    42             mxdis=std::max(mxdis,dis[pur]);
    43             mndis=std::min(mndis,dis[pur]);
    44         }
    45     }
    46     return mxdis-mndis+1;
    47 }
    48 int main(){
    49     n=read();m=read();
    50     for (int i=1;i<=m;i++){
    51         int x=read(),y=read();
    52         add(x,y);
    53     }
    54     int sum=0;
    55     for (int i=1;i<=n;i++)
    56      if (!vis[i]) sum+=bfs(i);
    57     len=std::abs(len);
    58     if (len){
    59         if (len<3) {
    60             printf("-1 -1
    ");
    61             return 0;
    62         }
    63         printf("%d ",len);
    64         for (int i=3;i<=len;i++)
    65          if (len%i==0) {
    66                 printf("%d
    ",i);
    67                 break;
    68          }
    69         return 0;
    70     }else
    71     if (sum<3){
    72         printf("-1 -1
    ");
    73         return 0;
    74     }else{
    75         printf("%d 3
    ",sum);
    76         return 0;
    77     }
    78 }
  • 相关阅读:
    Leetcode: Rotate Image
    Leetcode: Longest Palindromic Substring && Summary: Palindrome
    Leetcode: Reverse Nodes in k-Group
    Leetcode: Substring with Concatenation of All Words
    Leetcode: Merge k Sorted List
    Summary: Java中函数参数的传递
    Leetcode: Generate Parentheses
    超级wifi
    路由器中继(repeater)模式 和 AP+WDS模式区别?
    route 的标志位
  • 原文地址:https://www.cnblogs.com/qzqzgfy/p/5593607.html
Copyright © 2020-2023  润新知