BZOJ1064 NOI2008假面舞会

挺神的这题,发现只有环和链两种情况

搜索时我们只考虑环的,因为链可以看成找不到分类的环。

当成链时大小是的最大值是各链长的和,最小值是3

当成环时最大值是各环长的gcd,最小值是大于3的最小的ans的约数

当有链有环时只有当环的gcd大于等于3时才有解,所以我们统计答案时要优先考虑环的情况,考虑链情况时当且仅当没有环

By:大奕哥

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=1e5+10;
 4 int n,m,ans,ans2,pos[N],head[N],cnt,ma[N],mi[N],f[N];
 5 bool v[N];
 6 struct node{
 7     int to,nex,w;
 8 }e[2000005];
 9 void add(int x,int y,int w)
10 {
11     e[++cnt].to=y;e[cnt].nex=head[x];head[x]=cnt;e[cnt].w=w;
12 }
13 int gcd(int a,int b){return b==0?a:gcd(b,a%b);}
14 int get(int x){return x==f[x]?x:f[x]=get(f[x]);}
15 void dfs(int x,int tmp)
16 {
17     ma[tmp]=max(ma[tmp],pos[x]);
18     mi[tmp]=min(mi[tmp],pos[x]);v[x]=1;
19     for(int i=head[x];i;i=e[i].nex)
20     {
21         int y=e[i].to;
22         if(!v[y])
23         {
24             pos[y]=pos[x]+e[i].w;
25             dfs(y,tmp);
26         }
27         else ans=gcd(ans,abs(pos[x]-pos[y]+e[i].w)); 
28     }
29 }
30 int main()
31 {
32     scanf("%d%d",&n,&m);int x,y;
33     for(int i=1;i<=n;++i)f[i]=i;
34     for(int i=1;i<=m;++i)
35     {
36         scanf("%d%d",&x,&y);
37         add(x,y,1);add(y,x,-1);
38         int fx=get(x),fy=get(y);
39         f[fx]=fy;
40     }
41     memset(mi,0x3f,sizeof(mi));
42     for(int i=1;i<=n;++i)
43         if(!v[i]){
44             dfs(i,get(i));
45         }
46     if(ans<3)
47     {
48         if(!ans)
49         for(int i=1;i<=n;++i)
50         if(f[i]==i)
51         ans+=ma[i]-mi[i]+1;
52         if(ans<3)printf("-1 -1");
53         else
54         printf("%d 3",ans);
55     }
56     else
57     {
58         for(int i=3;i<=ans&&!ans2;++i)
59         if(ans%i==0)ans2=i;
60         printf("%d %d",ans,ans2);
61     }
62     return 0;
63 }

 

posted @ 2018-01-26 21:57  大奕哥&VANE  阅读(...)  评论(... 编辑 收藏