HDU-3038 How Many Answers Are Wrong

Topic link

HDU-3038

Title

Given an interval 1-n, the following m line gives the sum of one end of the continuous interval ab, if there is a conflict, ignore it, and ask how many instructions conflict

Ideas

Weighted union check set, we maintain an array value while maintaining the union check set. In this question, the sum of ab given can be regarded as the distance between a-1 node and b. We define the value array as the distance to the ancestor node. When the ancestors of a-1 and b are different, we connect them and update the value array. If they are the same, compare the weight difference of a-1 and b with Whether the given sum is equal, update the answer before waiting.
The framework has been set up, the following focuses on the design of the three functions of init, find and unite

  1. init (initialization) function

    Initialization is the simplest. In addition to setting the fa array, initialize the value array to 0.

    int init(){
          
          
    	for(int i=0;i<maxn;i++){
          
          
    		fa[i]=i;
    		va[i]=0;
    	}
    }
    
  2. find function

    The ordinary find function is the optimization of recursion plus path compression. After weighting, we need to update the value array.
    Before the update, we must first understand path compression. Path compression is to directly connect all the nodes involved in this search to the ancestor node after each find. As shown

    Insert picture description here

    In the above figure, we first link 12, and then connect 23. After the find function finds 1, connect 1 directly to root node 3. When we define the value array, this picture looks like this

    Insert picture description here

    After connecting to 12, our v1 is the distance of 1-2, after connecting to 23, v2 is the distance of 2-3, and at this time v1 has not been updated, it is not the root node we defined The distance is only the distance to his parent node, so in the find function, we should update v1. Obviously, the distance from 1 to root node 3 should be the value of 1 plus the value of parent node 2, that is, v1+v2. The specific code is:

    int find(int x){
          
          
    	if(fa[x]==x)
    		return x;
    	int root=find(fa[x]);//祖先节点 
    	va[x]+=va[fa[x]];//更新一下va 
    	return fa[x]=root; //将x直接连接到祖先节点上 
    }
    
  3. unite (connection) function

    This is the most troublesome design. Regardless of the optimization of merging according to anecdotes, the ordinary unique function only needs to merge the ancestors of the two nodes. Then how do we design with the value?

    Insert picture description here

    As shown in the figure, we connect 1, 3 nodes, then first find the root node 2, 4. We connect 2 to 4, the value of 4 is defined as 0, and the original value of 2 is 0. Now we need to update it, let v2 is the distance from 2 to 4. v1 is the distance between 1 and 2, and v3 is the distance between 3 and 4. In addition, the question also tells us the distance between 1 and 3. Then the path lengths of 1-2-4 and 1-3-4 should be equal. That is the equation written in the figure. The code is implemented as follows

    void unite(int x,int y,int v){
          
          
    	int fx=find(x),fy=find(y);
    	fa[fx]=fy;
    	va[fx]=v+va[y]-va[x];
    } 
    

So far, our three functions have been designed.

Code

#include<bits/stdc++.h>
using namespace std;
	const int maxn=200005;
	int fa[maxn];
	int va[maxn];//距离祖先节点的距离 
	
	int n,m;
	
	int init(){
    
    
		for(int i=0;i<maxn;i++){
    
    
			fa[i]=i;
			va[i]=0;
		}
	}
	 
	int find(int x){
    
    
		if(fa[x]==x)
			return x;
		int root=find(fa[x]);//祖先节点 
		va[x]+=va[fa[x]];//更新一下va 
		return fa[x]=root; //将x直接连接到祖先节点上 
	}
	
	void unite(int x,int y,int v){
    
    
		int fx=find(x),fy=find(y);
		fa[fx]=fy;
		va[fx]=v+va[y]-va[x];
	} 
	
	int main(){
    
    
		int n,m,ans,x,y,z;
		while(cin>>n>>m){
    
    
			ans=0;
			init();
			while(m--){
    
    
				cin>>x>>y>>z;
				x--;
				if(find(x)==find(y)){
    
    
					if(va[x]-va[y]!=z) 
						ans++;
				}
				else{
    
    
					unite(x,y,z);
				} 
			}
			cout<<ans<<endl;
		}
	}	

Guess you like

Origin blog.csdn.net/TheSunspot/article/details/107768182