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 }
生命中真正重要的不是你遭遇了什么,而是你记住了哪些事,又是如何铭记的。