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

什么叫神犇什么叫蒟蒻?

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。

//NOIp 0924 pod
//by Cydiater
//2016.9.24
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <map>
#include <ctime>
#include <cmath>
#include <iomanip>
#include <algorithm>
#include <string>
using namespace std;
#define ll long long
#define up(i,j,n)        for(int i=j;i<=n;i++)
#define down(i,j,n)        for(int i=j;i>=n;i--)
#define FILE "pod"
const int MAXN=1e6+5;
const int oo=0x3f3f3f3f;
inline int read(){
    char ch=getchar();int x=0,f=1;
    while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int N,M,Q,LINK[MAXN],len=0,f[MAXN],f2[MAXN],tol[MAXN];
struct edge{
    int x,y,next,v;
}e[MAXN<<1];
bool OK[MAXN];
namespace solution{
    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;}
    int gcd(int a,int b){return b==0?a:gcd(b,a%b);}
    int getf(int k){
        if(f[k]==k)        return k;
        f[k]=getf(f[k]);
        return f[k];
    }
    int getf2(int k){
        if(f2[k]==k)        return k;
        f2[k]=getf2(f2[k]);
        return f2[k];
    }
    void merge(int x,int y,int v){
        x=getf(x);y=getf(y);
        if(tol[x]!=0)v=gcd(v,tol[x]);
        if(tol[y]!=0)v=gcd(v,tol[y]);
        tol[x]=v;f[y]=x;
    }
    int merge2(int x,int y,int v){
        if(v==1){
            if(getf2(x)==getf2(y))        return 0;
            f2[getf2(x)]=getf2(y+N);
            f2[getf2(y)]=getf2(x+N);
        }else{
            if(getf2(x)==getf2(y+N))    return 0;
            f2[getf2(x)]=getf2(y);
            f2[getf2(x+N)]=getf2(y+N);
        }
        return 1;
    }
    void init(){
        N=read();M=read();Q=read();
        memset(tol,0,sizeof(tol));
        up(i,1,N){
            f[i]=i;f2[i]=i;
            f2[i+N]=i+N;
        }
        up(i,1,M){
            int x=read(),y=read(),v=read();
            insert(x,y,v);insert(y,x,v);
            merge(x,y,v);
        }
        up(i,1,M<<1){
            int x=e[i].x,y=e[i].y,v=e[i].v;
            int d=tol[getf(e[i].x)];
            int flag=merge2(x,y,(v/d)%2);
            if(!flag)OK[getf(x)]=1;
            i+=1;
        }
    }
    void slove(){
        while(Q--){
            int x=read(),y=read(),K=read();
            if(getf(x)!=getf(y))        puts("NIE");//unconnect
            else{
                int d=gcd(K,tol[getf(x)]);
                if((K/d)&1)                            puts("0");
                else{
                    if(OK[getf(x)])                    puts("0");
                    else{
                        if(getf2(x)==getf2(y))        puts("0");//same color
                        else                          printf("%d\n",d);
                    }
                }
            }
        }
    }
}
int main(){
    freopen(FILE".in","r",stdin);
    freopen(FILE".out","w",stdout);
    using namespace solution;
    init();
    slove();
    return 0;
}

NOIp模拟赛 旅游的更多相关文章

  1. NOIP模拟赛20161022

    NOIP模拟赛2016-10-22 题目名 东风谷早苗 西行寺幽幽子 琪露诺 上白泽慧音 源文件 robot.cpp/c/pas spring.cpp/c/pas iceroad.cpp/c/pas ...

  2. contesthunter暑假NOIP模拟赛第一场题解

    contesthunter暑假NOIP模拟赛#1题解: 第一题:杯具大派送 水题.枚举A,B的公约数即可. #include <algorithm> #include <cmath& ...

  3. NOIP模拟赛 by hzwer

    2015年10月04日NOIP模拟赛 by hzwer    (这是小奇=> 小奇挖矿2(mining) [题目背景] 小奇飞船的钻头开启了无限耐久+精准采集模式!这次它要将原矿运到泛光之源的矿 ...

  4. 大家AK杯 灰天飞雁NOIP模拟赛题解/数据/标程

    数据 http://files.cnblogs.com/htfy/data.zip 简要题解 桌球碰撞 纯模拟,注意一开始就在袋口和v=0的情况.v和坐标可以是小数.为保险起见最好用extended/ ...

  5. 队爷的讲学计划 CH Round #59 - OrzCC杯NOIP模拟赛day1

    题目:http://ch.ezoj.tk/contest/CH%20Round%20%2359%20-%20OrzCC杯NOIP模拟赛day1/队爷的讲学计划 题解:刚开始理解题意理解了好半天,然后发 ...

  6. 队爷的Au Plan CH Round #59 - OrzCC杯NOIP模拟赛day1

    题目:http://ch.ezoj.tk/contest/CH%20Round%20%2359%20-%20OrzCC杯NOIP模拟赛day1/队爷的Au%20Plan 题解:看了题之后觉得肯定是DP ...

  7. 队爷的新书 CH Round #59 - OrzCC杯NOIP模拟赛day1

    题目:http://ch.ezoj.tk/contest/CH%20Round%20%2359%20-%20OrzCC杯NOIP模拟赛day1/队爷的新书 题解:看到这题就想到了 poetize 的封 ...

  8. CH Round #58 - OrzCC杯noip模拟赛day2

    A:颜色问题 题目:http://ch.ezoj.tk/contest/CH%20Round%20%2358%20-%20OrzCC杯noip模拟赛day2/颜色问题 题解:算一下每个仆人到它的目的地 ...

  9. CH Round #52 - Thinking Bear #1 (NOIP模拟赛)

    A.拆地毯 题目:http://www.contesthunter.org/contest/CH%20Round%20%2352%20-%20Thinking%20Bear%20%231%20(NOI ...

随机推荐

  1. ul、li实现横向导航按钮

    好久没写博客了,主要是懒得呼气都不想呼,上周分给我一个新的任务,就是自己新建一个系统,快速极限开发,虽然之前自己也做过小的系统,但毕竟是自己做,随着自己的心意做,没有做其他的限制等,现在呢是给公司做, ...

  2. 自己存档:asp.net mvc 从filterContent得到controller和action

    //filterContext.RouteData.GetRequiredString("controller") + "/" + filterContext. ...

  3. Python 处理数据库返回结果

    游标执行后返回的结果都只是数据,但是不带有列名标识.这里需要处理2个问题: 将返回的数据映射到每一列上 当返回的结果很大的时候,需要使用迭代器来提升性能. 解决上面的2个问题,在python里面可以采 ...

  4. [BZOJ1188][HNOI2007]分裂游戏(博弈论)

    题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1188 分析: 设SG[i]表示一个石子在位置i上的SG值 这个很容易暴力求,因为i的后 ...

  5. 最短判断IE的办法

    if(!!-[1,]){ return }; 无意中看到这样一行代码,经查是用来判断IE的代码,非常精简,原理如下: [1,],这是一个数组,IE和标准浏览器对这样一个数组的解析是不一样的 alert ...

  6. ubuntu完全卸载nginx

    删除nginx连带配置文件 sudo apt-get purge nginx # Removes everything. 卸载不再需要的nginx依赖程序 sudo apt-get autoremov ...

  7. RAP在centos上的部署

    在centos7上部署RAP(非官方) 作者批注:该部署文档为网友贡献,仅供参考.war请参考主页README.md下载最新版本哟~~~ 感谢热情网友的Wiki整理!万分感谢! 系统: centos7 ...

  8. 【转】C#判断奇偶数的函数

    // 现代流行的"程序员" public static bool IsOdd(int n) { while (true) { switch (n) { : return true; ...

  9. 如何让div显示在embed,flash元素之上

    Z-INDEX属性只对块状元素有效,对于flash是没用的,那么我们怎么处理这个问题呢,问大家介绍两种很简便的方法 方法一 把<embed>标记写在<object>之内 方法二 ...

  10. css 选择器样式优先级

    !important > 行内 >id > class >tag >*