2017.7.10 noi2008 假面舞会

首先,可以把每个人看成一个点,能看见谁就相当于两个人之间有一个单向边,这样就可以把关系看成几个连通图。

对于每个连通图,有三种情况:

1.所有边数之和的最大公约数

2.正向边和反向边差的绝对值的最大公约数

3.是一条链

记录的时候可以把正向边记为+1,反向边记为-1,遍历的时候只要记录图中的加和 就可以得知前两种情况,然后取gcd就是max,min是最小的、大于3的、max的约数。

如果在最后没有找到环,说明只有链能限制,这时就算出每个连通图中最长链,然后加和为max,min就是3了。

而如果有环,那么只能按环算,因为链无论如何也能满足,而环不行。

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<iostream>
  4 #include<algorithm>
  5 #include<vector>
  6 #define mem(a,b) memset(a,b,sizeof(a))
  7 using namespace std;
  8 int read()
  9 {
 10     int ans=0;char q=getchar();
 11     while(q<‘0‘||q>‘9‘)q=getchar();
 12     while(q>=‘0‘&&q<=‘9‘){ans=ans*10+q-‘0‘;q=getchar();}
 13     return ans;
 14 }
 15 int gcd(int x,int y){return y==0?x:gcd(y,x%y);}
 16 int abss(int x){return x<0?-x:x;}
 17 int maxn(int a,int b){return a>b?a:b;}
 18 int minn(int a,int b){return a<b?a:b;}
 19 struct son
 20 {
 21     int v,next,w;
 22 };
 23 son a1[6000001];
 24 int first[6000001],e;
 25
 26 void addbian(int u,int v,int w)
 27 {
 28     a1[e].w=w;
 29     a1[e].v=v;
 30     a1[e].next=first[u];
 31     first[u]=e++;
 32 }
 33
 34 int n,m,u,o;
 35 int vis[600001];
 36 int ans;
 37 int w[600001];
 38 int maxl,minl;
 39
 40 void dfs(int fa,int x,int val)
 41 {
 42     //printf("x=%d val=%d\n",x,val);
 43     vis[x]=1;
 44     w[x]=val;
 45     for(int i=first[x];i!=-1;i=a1[i].next)
 46     {
 47         int temp=a1[i].v;
 48         if(temp==fa)continue;
 49         if(vis[temp])
 50         {
 51             if(val==0)continue;
 52             ans=gcd(ans,abss(val+a1[i].w-w[temp]));
 53             //printf("val=%d temp=%d ans=%d\n",val,temp,ans);
 54             continue;
 55         }
 56         dfs(x,temp,val+a1[i].w);
 57     }
 58 }
 59
 60 void dfs2(int fa,int x,int val)
 61 {
 62     vis[x]=1;
 63     maxl=maxn(maxl,val);
 64     minl=minn(minl,val);
 65     for(int i=first[x];i!=-1;i=a1[i].next)
 66     {
 67         int temp=a1[i].v;
 68         if(vis[temp]||temp==fa)continue;
 69         dfs2(x,temp,val+a1[i].w);
 70     }
 71 }
 72
 73 int main(){
 74     //freopen("party.in","r",stdin);
 75     //freopen("party.out","w",stdout);
 76     /////freopen("1.txt","r",stdin);
 77     //freopen("2.txt","w",stdout);
 78     mem(first,-1);
 79     n=read();m=read();
 80     for(int i=1;i<=m;++i)
 81     {
 82         u=read();o=read();
 83         addbian(u,o,1);
 84         addbian(o,u,-1);
 85     }
 86     //cout<<0;
 87     for(int i=1;i<=n;++i)
 88     {
 89         if(vis[i])continue;
 90         dfs(-1,i,0);
 91     }
 92
 93     if(ans)
 94     {
 95         if(ans<3)
 96           printf("-1 -1");
 97         else
 98         {
 99             printf("%d ",ans);
100             for(int i=3;i<=ans;++i)
101               if(!(ans%i))
102               {
103                 printf("%d",i);
104                     break;
105                 }
106         }
107     }
108     else
109     {
110         mem(w,0);
111         mem(vis,0);
112         for(int i=1;i<=n;++i)
113         {
114             if(vis[i])continue;
115             maxl=minl=0;
116             dfs2(-1,i,0);
117             //ans=maxn(maxl1+maxl2-1,ans);
118             ans+=(maxl-minl+1);
119         }
120         //printf("ans=%d\n",ans);
121         if(ans<3)
122           printf("-1 -1");
123         else
124           printf("%d 3",ans);
125     }
126
127     //while(1);
128     return 0;
129 }

最后附上代码

时间: 2024-10-13 00:01:58

2017.7.10 noi2008 假面舞会的相关文章

BZOJ 1064[NOI2008]假面舞会

1064: [Noi2008]假面舞会 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2044  Solved: 989[Submit][Status][Discuss] Description 一年一度的假面舞会又开始了,栋栋也兴致勃勃的参加了今年的舞会.今年的面具都是主办方特别定制的.每个参加舞会的人都可以在入场时选择一 个自己喜欢的面具.每个面具都有一个编号,主办方会把此编号告诉拿该面具的人.为了使舞会更有神秘感,主办方把面具分为k (k≥

图论 公约数 找环和链 BZOJ [NOI2008 假面舞会]

BZOJ 1064: [Noi2008]假面舞会 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1655  Solved: 798[Submit][Status][Discuss] Description 一年一度的假面舞会又开始了,栋栋也兴致勃勃的参加了今年的舞会.今年的面具都是主办方特别定制的.每个参加舞会的人都可以在入场时选择一 个自己喜欢的面具.每个面具都有一个编号,主办方会把此编号告诉拿该面具的人.为了使舞会更有神秘感,主办方把面具分为

【BZOJ 1064】 [Noi2008]假面舞会

1064: [Noi2008]假面舞会 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 988  Solved: 507 [Submit][Status] Description 一年一度的假面舞会又开始了,栋栋也兴致勃勃的参加了今年的舞会.今年的面具都是主办方特别定制的.每个参加舞会的人都可以在入场时选择一 个自己喜欢的面具.每个面具都有一个编号,主办方会把此编号告诉拿该面具的人.为了使舞会更有神秘感,主办方把面具分为k (k≥3)类,并使用特

NOI2008假面舞会

1064: [Noi2008]假面舞会 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 883  Solved: 462[Submit][Status] Description 一年一度的假面舞会又开始了,栋栋也兴致勃勃的参加了今年的舞会.今年的面具都是主办方特别定制的.每个参加舞会的人都可以在入场时选择一 个自己喜欢的面具.每个面具都有一个编号,主办方会把此编号告诉拿该面具的人.为了使舞会更有神秘感,主办方把面具分为k (k≥3)类,并使用特殊的

[BZOJ1064][Noi2008]假面舞会

试题描述 一年一度的假面舞会又开始了,栋栋也兴致勃勃的参加了今年的舞会.今年的面具都是主办方特别定制的.每个参加舞会的人都可以在入场时选择一 个自己喜欢的面具.每个面具都有一个编号,主办方会把此编号告诉拿该面具的人.为了使舞会更有神秘感,主办方把面具分为k (k≥3)类,并使用特殊的技术将每个面具的编号标在了面具上,只有戴第i 类面具的人才能看到戴第i+1 类面具的人的编号,戴第k 类面具的人能看到戴第1 类面具的人的编号. 参加舞会的人并不知道有多少类面具,但是栋栋对此却特别好奇,他想自己算出

【BZOJ】1064: [Noi2008]假面舞会(判环+gcd+特殊的技巧)

http://www.lydsy.com/JudgeOnline/problem.php?id=1064 表示想到某一种情况就不敢写下去了.... 就是找环的gcd...好可怕.. 于是膜拜了题解.. 和我想的差不多.. 首先发现这3几种情况: 1.一条或多条单链,那么最多有sum{单链长度}个面具,最少有3个面具 2.环.主要是大环套小环QAQ,显然我们只要小环就行了QAQ环的长度为标号差,gcd能满足这个性质,因此不管它.找出所有的环即可. 3.链相交.此时最大为相交链的长度差的gcd,最小

BZOJ1064 [Noi2008]假面舞会 【dfs】

题目 一年一度的假面舞会又开始了,栋栋也兴致勃勃的参加了今年的舞会.今年的面具都是主办方特别定制的.每个参加舞会的人都可以在入场时选择一 个自己喜欢的面具.每个面具都有一个编号,主办方会把此编号告诉拿该面具的人.为了使舞会更有神秘感,主办方把面具分为k (k≥3)类,并使用特殊的技术将每个面具的编号标在了面具上,只有戴第i 类面具的人才能看到戴第i+1 类面具的人的编号,戴第k 类面具的人能看到戴第1 类面具的人的编号. 参加舞会的人并不知道有多少类面具,但是栋栋对此却特别好奇,他想自己算出有多

【图论 搜索】bzoj1064: [Noi2008]假面舞会

做到最后发现还是读题比赛 Description 一年一度的假面舞会又开始了,栋栋也兴致勃勃的参加了今年的舞会.今年的面具都是主办方特别定制的.每个参加舞会的人都可以在入场时选择一 个自己喜欢的面具.每个面具都有一个编号,主办方会把此编号告诉拿该面具的人.为了使舞会更有神秘感,主办方把面具分为k (k≥3)类,并使用特殊的技术将每个面具的编号标在了面具上,只有戴第i 类面具的人才能看到戴第i+1 类面具的人的编号,戴第k 类面具的人能看到戴第1 类面具的人的编号. 参加舞会的人并不知道有多少类面

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,a