zoukankan      html  css  js  c++  java
  • wikioi1450 xth的旅行

    毕业了,Xth很高兴,因为他要和他的 rabbit 去双人旅行了。他们来到了水城威尼
    斯。众所周知(⊙﹏⊙b汗),这里的水路交通很发达,所以 xth 和 rabbit 只好坐
    船穿梭于各个景点之间。但是要知道,rabbit 是会晕船的,看到她难受,xth 是会
    心疼的。
    已知城市中有n个景点,这些景点之间有m条双向水路,在每条水路上航行时
    rabbit 都会有一个“晕船值”。旅行时,xth 会带着 rabbit 尽量选择晕船值小的路线
    旅行。但是 rabbit 也是有一定忍耐限度度的,如果晕船值超过了她的忍耐度,xth
    会果断决定放弃这条路线。
    现在 xth 想进行若干次询问,给定 rabbit 的忍耐度,问还有多少对城市(x,y)间会存
    在可行的旅行路线(如果(x,z)和(z, y)可行,则(x,y)可行,也就是说连通性是可传
    递的)。

    第 1 行三个正整数n、m、q,分别表示景点数量、水路数量和询问次数。
    第 2 行到第m + 1行每行三个正整数x、y、w,表示x号景点和y号景点之间有一条
    “晕船值”为w的双向水路。
    第m + 2行至第m + q + 1行,每行一个正整数k,表示询问中给定的 rabbi忍耐度
    为k。

    共q行,对于每次询问做出回答。

    5 5 2

    1 2 1

    2 3 2

    3 4 1

    4 5 4

    5 1 1

    1

    2

    4

    10

    第一个询问:(1,2), (1,5), (2,5), (3,4)。其中(2,5)的具体走法为:2 − 1 − 5
    第二个询问:(1,2), (1,3), (1,4), (1,5), (2,3), (2,4), (2,5), (3,4), (3,5), (4,5)。其中(4,5)
    的具体走法为:4 − 3 − 2 − 1 − 5

    对于20%的数据满足n ≤ 20,m ≤ 40,q ≤ 40;
    对于40%的数据满足n ≤ 1000,m ≤ 2000,q ≤ 1000;
    对于60%的数据满足n ≤ 3000,m ≤ 6000,q ≤ 200000;
    对于100%的数据满足n ≤ 100000,m ≤ 200000,q ≤ 200000。其他数不超过10^9。

    并查集……先把询问排序,然后按顺序添加边。

    维护当前联通块中的节点个数x,则这块联通块对答案的贡献是x*(x-1)/2

    原来想的是用平衡树维护合并操作后的节点数,但是其实只要算出合并的两个联通块的大小x、y,ans减去x*(x-1)/2和y*(y-1)/2加上(x+y)*(x+y-1)/2就好了……毕竟我SX

    我记得了ans数组开long long,结果输出用%d……稀里糊涂的wa来wa去

    #include<cstdio>
    #include<algorithm>
    #define LL long long
    using namespace std;
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    inline void swap(int &a,int &b)
    {int t=a;a=b;b=t;}
    struct query{
    	int k,rank;
    }q[200010];
    inline bool cmp(const query &a,const query &b){return a.k<b.k;}
    struct edge{
    	int x,y,k;
    }e[200010];
    inline bool cmp2(const edge &a,const edge &b){return a.k<b.k;}
    int fa[200010];
    int size[200010];
    LL ans[200010];
    LL res;
    int n,m,Q,now,piece;
    inline int getfa(int x)
    {return fa[x]==x?x:fa[x]=getfa(fa[x]);}
    inline void merge(int now)
    {
    	int x=getfa(e[now].x),y=getfa(e[now].y);
    	if (x==y)return;
    	if (x>y)swap(x,y);
    	LL szx=size[x],szy=size[y],tot=szx+szy;
    	res-= szx*(szx-1)/2+szy*(szy-1)/2;
    	res+= tot*(tot-1)/2;
    	fa[x]=y;size[y]=size[x]=tot;
    }
    int main()
    {
    	n=read();m=read();Q=read();
    	for (int i=1;i<=n;i++)fa[i]=i,size[i]=1;
    	for (int i=1;i<=m;i++)
    	{
    		e[i].x=read();e[i].y=read();e[i].k=read();
    		if (e[i].x>e[i].y)swap(e[i].x,e[i].y);
    	}
    	sort(e+1,e+m+1,cmp2);
    	for (int i=1;i<=Q;i++)q[i].k=read(),q[i].rank=i;
    	sort(q+1,q+Q+1,cmp);
    	for (int i=1;i<=Q;i++)
    	  {
    	  	if (e[now].k>q[i].k)
    	  	{
    	  		ans[q[i].rank]=res;
    	  		continue;
    	  	}
    	  	while (now<m&&e[now+1].k<=q[i].k)merge(++now);
    	  	ans[q[i].rank]=res;
    	  }
    	for(int i=1;i<=Q;i++)
    	  printf("%lld
    ",ans[i]);
    }
    

      

    ——by zhber,转载请注明来源
  • 相关阅读:
    求两条链表有无交点和第一个交点
    重载自增运算符(前置自增++p和后置自增p++)
    二叉排序树和平衡二叉树
    红黑树
    java学习攻略
    Intellij IDEA / IntelliJ
    ngrinder test
    eclipsejeekeplerSR2win32x86_64 jsonedit plugin
    向叶子文文的.net之路学习(大量的转载)
    微软发布机制(转)从浅入深
  • 原文地址:https://www.cnblogs.com/zhber/p/4036001.html
Copyright © 2011-2022 走看看