[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 }
原文地址:https://www.cnblogs.com/cervusy/p/9622994.html