zoukankan      html  css  js  c++  java
  • [2018.12.27]BZOJ4690 Never Wait for Weights

    首先我们发现UNKNOWN很好判断,写个并查集就好了。

    考虑如何算出同一并查集内任意元素的权值差。

    设两点(a,b),另一点(c)

    则答案(b-a=(b-c)-(a-c))

    发现(c)可以是同一并查集中任意的点。

    考虑使用这个并查集的根。

    (f_x)为并查集中(x)的父亲,(d_x)为第(x)个样品比它的父亲这个样品轻多少。

    则我们在将(x)的父亲更新到(f_{f_x})时,要将(d_x)设为(d_x+d_{f_x})

    合并类似,但是我太懒难以表述,所以可以自己看代码(应该很清楚吧?)。

    code:

    #include<bits/stdc++.h>
    using namespace std;
    int n,m,a,b,w,f[100010],d[100010];
    char op;
    void getc(char &c){
    	c=getchar();
    	while(c!='!'&&c!='?')c=getchar();
    }
    int getf(int x){
    	if(f[x]==x)return x;
    	int t=getf(f[x]);
    	d[x]+=d[f[x]];
    	return f[x]=f[f[x]];
    }
    void merge(int x,int y,int v){
    	if(getf(x)==getf(y))return;
    	d[f[x]]=v-d[x]+d[y];
    	f[f[x]]=f[y];
    }
    int main(){
    	while(scanf("%d%d",&n,&m)){
    		if(!n)return 0;
    		for(int i=1;i<=n;i++)f[i]=i,d[i]=0;
    		while(m--){
    			getc(op);
    			if(op=='!')scanf("%d%d%d",&a,&b,&w),merge(a,b,w);
    			else{
    				scanf("%d%d",&a,&b);
    				if(getf(a)!=getf(b))puts("UNKNOWN");
    				else printf("%d
    ",d[a]-d[b]);
    			}
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    杜教筛
    虚树
    带修莫队
    线性基
    区间修改区间求和cdq分治
    矩阵快速幂求斐波那契数列
    点分治成品
    Codeforces Round #542 [Alex Lopashev Thanks-Round] (Div. 1) C(二分+KMP)
    线性筛
    矩阵快速幂
  • 原文地址:https://www.cnblogs.com/xryjr233/p/BZOJ4690.html
Copyright © 2011-2022 走看看