BZOJ1064 NOI2008假面舞会

本文探讨了一种基于图论的问题解决方法,通过将问题抽象为环和链的形式,并利用搜索算法来确定最大值和最小值。针对不同类型的图结构,如环状结构和链状结构,提出了有效的算法实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

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

当成链时大小是的最大值是各链长的和,最小值是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 }

 

转载于:https://www.cnblogs.com/nbwzyzngyl/p/8361768.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值