NOIp模拟赛 旅游

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NOIp模拟赛 旅游相关的知识,希望对你有一定的参考价值。

技术分享技术分享

 

 很神奇的一道题,金策大爷给的题解:

技术分享

 

什么叫神犇什么叫蒟蒻?

IOI冠军的一句基本相同让我思考了一下午。

 

看完了题解我就想都没想开始用遍历二分图搞,但是搞到了65分后就总是会WA掉7组。

然后仔细的看了看std,位运算上对几处做了常数上的优化,读起来异常麻烦,到最后看懂他在干什么了。但是总是不理解。

下午浪费了两节英语课思考原理,总之想明白了。

 

我简单说一下我的想法。

首先考虑如果一条路径的所有边权的gcd为$d$,那么不管正着走反着走或者绕上几圈,其总路径和一定为$kd$,$k$为任意正整数。

这一点学过gcd应该都很好想到。那么很显然的一件事就是如果一张图中两个相通的点,从一个点到另一个点的总路径和也一定为$kd$,$d$为这个连通分量里所有边权的gcd。同样的,如果需要把答案mod$K$,只需要$d=gcd(K,d)$即可,最后的答案一定是$d$或者0。这点转化是这道题的第一步。但不是最重要的一步。

 

这时候就把问题转化为了从$node_i$到$node_j$是否存在一条路径,使得其总长为$cK$,$c$为任意正整数。如果存在,显然答案为0,如果不存在,那么答案就是$d$。同时,需要提前用并查集判断连通性。

 

首先,考虑$K$为奇数的情况,在这种情况下,只要两点联通,答案一定为0,因为如果K为奇数,而假设从$node_i$到$node_j$的最短路径为$h$,那么一定存在一个数$b$使得$bh=cK$,如果想到了这点。就能拿到20分的部分分。

然后我们是否应该考虑$K$为偶数的情况?

 

并不,相对来说有更通用的情况。回到前面,我们已经得出了如果把总路径$modK$,那么一定存在一种方案使得从$node_i$到$node_j$的长度为$d$,这时候如果$K$为$d$的奇数倍,那么显然答案为0。

再思考,既然$d$为这个连通分量里所有边权的gcd,这也就意味着所有边的边权都是$d$的整数倍,也就是说所有边都可以拆成任意整数个边权为$d$的边。而如果存在一个数使得$hd==cK$,那么答案就是0。

那么是否可以把每个点拆为$node_i$和$node_{i+N}$,其中的两个点集之间相连的边的长度是奇数个$d$,而任意一个点集里的点之间的边都是偶数个$d$,这个显然可以用并查集维护。

这时候如果$node_i$和$node_j$位于一个点集,显然其是存在为0的答案。

 

但是除此之外,还存在特殊的情况。如果从一个点到另一个点既存在奇数个$d$的路径,也存在偶数个$d$的路径。怎么处理?

 

这时候只需要把这个联通块标记即可,这个连通块的任意两点之间到达的答案均为0。

 

技术分享
  1 //NOIp 0924 pod
  2 //by Cydiater
  3 //2016.9.24
  4 #include <iostream>
  5 #include <cstring>
  6 #include <cstdlib>
  7 #include <cstdio>
  8 #include <queue>
  9 #include <map>
 10 #include <ctime>
 11 #include <cmath>
 12 #include <iomanip>
 13 #include <algorithm>
 14 #include <string>
 15 using namespace std;
 16 #define ll long long
 17 #define up(i,j,n)        for(int i=j;i<=n;i++)
 18 #define down(i,j,n)        for(int i=j;i>=n;i--)
 19 #define FILE "pod"
 20 const int MAXN=1e6+5;
 21 const int oo=0x3f3f3f3f;
 22 inline int read(){
 23     char ch=getchar();int x=0,f=1;
 24     while(ch>9||ch<0){if(ch==-)f=-1;ch=getchar();}
 25     while(ch>=0&&ch<=9){x=x*10+ch-0;ch=getchar();}
 26     return x*f;
 27 }
 28 int N,M,Q,LINK[MAXN],len=0,f[MAXN],f2[MAXN],tol[MAXN];
 29 struct edge{
 30     int x,y,next,v;
 31 }e[MAXN<<1];
 32 bool OK[MAXN];
 33 namespace solution{
 34     inline void insert(int x,int y,int v){e[++len].next=LINK[x];LINK[x]=len;e[len].y=y;e[len].v=v;e[len].x=x;}
 35     int gcd(int a,int b){return b==0?a:gcd(b,a%b);}
 36     int getf(int k){
 37         if(f[k]==k)        return k;
 38         f[k]=getf(f[k]);
 39         return f[k];
 40     }
 41     int getf2(int k){
 42         if(f2[k]==k)        return k;
 43         f2[k]=getf2(f2[k]);
 44         return f2[k];
 45     }
 46     void merge(int x,int y,int v){
 47         x=getf(x);y=getf(y);
 48         if(tol[x]!=0)v=gcd(v,tol[x]);
 49         if(tol[y]!=0)v=gcd(v,tol[y]);
 50         tol[x]=v;f[y]=x;
 51     }
 52     int merge2(int x,int y,int v){
 53         if(v==1){
 54             if(getf2(x)==getf2(y))        return 0;
 55             f2[getf2(x)]=getf2(y+N);
 56             f2[getf2(y)]=getf2(x+N);
 57         }else{
 58             if(getf2(x)==getf2(y+N))    return 0;
 59             f2[getf2(x)]=getf2(y);
 60             f2[getf2(x+N)]=getf2(y+N);
 61         }
 62         return 1;
 63     }
 64     void init(){
 65         N=read();M=read();Q=read();
 66         memset(tol,0,sizeof(tol));
 67         up(i,1,N){
 68             f[i]=i;f2[i]=i;
 69             f2[i+N]=i+N;
 70         }
 71         up(i,1,M){
 72             int x=read(),y=read(),v=read();
 73             insert(x,y,v);insert(y,x,v);
 74             merge(x,y,v);
 75         }
 76         up(i,1,M<<1){
 77             int x=e[i].x,y=e[i].y,v=e[i].v;
 78             int d=tol[getf(e[i].x)];
 79             int flag=merge2(x,y,(v/d)%2);
 80             if(!flag)OK[getf(x)]=1;
 81             i+=1;
 82         }
 83     }
 84     void slove(){
 85         while(Q--){
 86             int x=read(),y=read(),K=read();
 87             if(getf(x)!=getf(y))        puts("NIE");//unconnect
 88             else{
 89                 int d=gcd(K,tol[getf(x)]);
 90                 if((K/d)&1)                            puts("0");
 91                 else{
 92                     if(OK[getf(x)])                    puts("0");
 93                     else{
 94                         if(getf2(x)==getf2(y))        puts("0");//same color
 95                         else                          printf("%d\\n",d);
 96                     }
 97                 }
 98             }
 99         }
100     }
101 }
102 int main(){
103     freopen(FILE".in","r",stdin);
104     freopen(FILE".out","w",stdout);
105     using namespace solution;
106     init();
107     slove();
108     return 0;
109 }
View Code

 

以上是关于NOIp模拟赛 旅游的主要内容,如果未能解决你的问题,请参考以下文章

B. 那一天她离我而去(noip模拟赛)

NOIP2017模拟8.8Trip

noip模拟 市长选举

cojs 1175. [顾研NOIP] 旅游电车

COGS——T 1175. [顾研NOIP] 旅游电车

NOIP2017旅游(过节)总结