HDU 3038 How Many Answers Are Wrong (并查集路径压缩)

How Many Answers Are Wrong

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1609 Accepted Submission(s): 646

Problem Description
TT and FF are ... friends. Uh... very very good friends -________-b

FF is a bad boy, he is always wooing TT to play the following game with him. This is a very humdrum game. To begin with, TT should write down a sequence of integers-_-!!(bored).

Then, FF can choose a continuous subsequence from it(for example the subsequence from the third to the fifth integer inclusively). After that, FF will ask TT what the sum of the subsequence he chose is. The next, TT will answer FF's question. Then, FF can redo this process. In the end, FF must work out the entire sequence of integers.

Boring~~Boring~~a very very boring game!!! TT doesn't want to play with FF at all. To punish FF, she often tells FF the wrong answers on purpose.

The bad boy is not a fool man. FF detects some answers are incompatible. Of course, these contradictions make it difficult to calculate the sequence.

However, TT is a nice and lovely girl. She doesn't have the heart to be hard on FF. To save time, she guarantees that the answers are all right if there is no logical mistakes indeed.

What's more, if FF finds an answer to be wrong, he will ignore it when judging next answers.

But there will be so many questions that poor FF can't make sure whether the current answer is right or wrong in a moment. So he decides to write a program to help him with this matter. The program will receive a series of questions from FF together with the answers FF has received from TT. The aim of this program is to find how many answers are wrong. Only by ignoring the wrong answers can FF work out the entire sequence of integers. Poor FF has no time to do this job. And now he is asking for your help~(Why asking trouble for himself~~Bad boy)
 
Input
Line 1: Two integers, N and M (1 <= N <= 200000, 1 <= M <= 40000). Means TT wrote N integers and FF asked her M questions.

Line 2..M+1: Line i+1 contains three integer: Ai, Bi and Si. Means TT answered FF that the sum from Ai to Bi is Si. It's guaranteed that 0 < Ai <= Bi <= N.

You can assume that any sum of subsequence is fit in 32-bit integer.
 
Output
A single line with a integer denotes how many answers are wrong.
 
Sample Input
10 5 1 10 100 7 10 28 1 3 32 4 6 41 6 6 1
 
Sample Output
1
 



题意:有N个数和M条信息,没条信息包含3个数 a b c ,表示第 a 个数到第 b 个数的和为 c 。
如果第 i 条信息与前 i-1 条信息没有冲突,则认为它是真的,否则是假的。问假信息有多少条。


思路:并查集路径压缩


怎么用并查集解的呢?首先做一点小处理,将 a-- 。为什么要这样呢,题目给的是一个闭区间[a,b]的和

把它换成一个半开半闭区间 (a--,b] 。半开半闭区间有个优良的性质: (a,b] + (b,c] = (a,c]

再来看这 M 条信息,对于一条信息 a,b,c 怎么解读它呢?我们可以把它解读为:a与b有关系,它们的关系有一个权值c

将关系用并查集的方式存储下来,那么对于处于同一个集合里面的元素两两之间的关系权值要么已知,要么可以推算出来。

原因很简单 (a,b] + (b,c] = (a,c] 。那么当新来一条信息 ai,bi,ci 时,判断 ai,bi 是不是在一个集合里。如果不在,将 ai,bi所处

的集合合并;如果在,判断一下 ci 是否等于 ai,bi 的关系权值。

现在,大体上的思路已经明了。剩下的问题是,怎么去维护关系权值呢?两两去算去存显然很麻烦,时间空间复杂度也不允许。

这些权值是建立在关系上的,还得让并查集来帮忙。建立一个weight[]数组,weight[a] 表示 a 与它当前的老大per[a]的关系权值。

如果说 a,b 有关系,那么 a,b 间的关系权值就等于 weight[b] - weight[a] (这里假设b>a)

来源于: http://blog.csdn.net/Magic_insky/article/details/9904469

import java.io.*;
import java.util.*;
public class Main {
	static int n,m;
	static int patten[]=new int[200002];
	static int sum[]=new int[1000000];
	static int num;
	public static void main(String[] args) {
		Scanner sc=new Scanner(new BufferedInputStream(System.in));
		while(sc.hasNext()){
			n=sc.nextInt();
			m=sc.nextInt();
			//并查集初始化
			for(int i=1;i<=n;i++){
				patten[i]=i;
			}
			Arrays.fill(sum,0);
			num=0;
			for(int i=0;i<m;i++){
				int a=sc.nextInt();
				int b=sc.nextInt();
				int c=sc.nextInt();
				a--;// 题目答案给的是闭区间[a,b]  我们要求的是开区间(a,b)所以要减减
				union(a,b,c);
			}
			System.out.println(num);
		}
	}
	//并查集合并
	static void  union(int a,int b,int c){
		int pa=find(a);
		int pb=find(b);
		if(pa==pb){
			if((sum[b]-sum[a])!=c)
				num++;
			
		}else{
			patten[pb]=pa;
			sum[pb]=sum[a]-sum[b]+c;
		}
	}
	// 并查集查找
	static int find(int x){
		
		if(x==patten[x])
			return x;
		int t=patten[x];
		patten[x]=find(t);//路径压缩
		sum[x]+=sum[t];
		return patten[x];

	}
}



原文地址:https://www.cnblogs.com/bbsno1/p/3266656.html