zoukankan      html  css  js  c++  java
  • BZOJ1202 [HNOI2005]狡猾的商人 【并查集】

    1202: [HNOI2005]狡猾的商人

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 4180  Solved: 2015
    [Submit][Status][Discuss]

    Description

    刁姹接到一个任务,为税务部门调查一位商人的账本,看看账本是不是伪造的。账本上记录了n个月以来的收入情况,其中第i 个月的收入额为Ai(i=1,2,3...n-1,n), 。当 Ai大于0时表示这个月盈利Ai 元,当 Ai小于0时表示这个月亏损Ai 元。所谓一段时间内的总收入,就是这段时间内每个月的收入额的总和。 刁姹的任务是秘密进行的,为了调查商人的账本,她只好跑到商人那里打工。她趁商人不在时去偷看账本,可是她无法将账本偷出来,每次偷看账本时她都只能看某段时间内账本上记录的收入情况,并且她只能记住这段时间内的总收入。 现在,刁姹总共偷看了m次账本,当然也就记住了m段时间内的总收入,你的任务是根据记住的这些信息来判断账本是不是假的。

    Input

    第一行为一个正整数w,其中w < 100,表示有w组数据,即w个账本,需要你判断。每组数据的第一行为两个正整数n和m,其中n < 100,m < 1000,分别表示对应的账本记录了多少个月的收入情况以及偷看了多少次账本。接下来的m行表示刁姹偷看m次账本后记住的m条信息,每条信息占一行,有三个整数s,t和v,表示从第s个月到第t个月(包含第t个月)的总收入为v,这里假设s总是小于等于t。

    Output

    包含w行,每行是true或false,其中第i行为true当且仅当第i组数据,即第i个账本不是假的;第i行为false当且仅当第i组数据,即第i个账本是假的。

    Sample Input

    2
    3 3
    1 2 10
    1 3 -5
    3 3 -15
    5 3
    1 5 100
    3 5 50
    1 2 51

    Sample Output

    true
    false


    我图形思维还是太弱了QAQ

    短短并查集查了那么久

    由题,只有当我们直接或间接得到两个相同的区间信息不同时为false

    按照前缀和的思想,区间和[a,b] = z可以写成s[b] - s[a - 1] = z

    这样子我们就转化为了两个点之间的关系,每当我们得出两点的关系时,我们将它们所在集合合并

    两点关系确定,当且仅当两点在同一并查集中

    我们再维护每一点到所在并查集根节点的距离表示s[a] - s[root]

    这样当我们需要b - a的时,只需将d[b] - d[a]


    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define LL long long int
    #define REP(i,n) for (int i = 1; i <= (n); i++)
    #define fo(i,x,y) for (int i = (x); i <= (y); i++)
    #define Redge(u) for (int k = head[u]; k != -1; k = edge[k].next)
    using namespace std;
    const int maxn = 105,maxm = 100005,INF = 1000000000;
    inline int read(){
    	int out = 0,flag = 1;char c = getchar();
    	while (c < 48 || c > 57) {if (c == '-') flag = -1; c = getchar();}
    	while (c >= 48 && c <= 57) {out = out * 10 + c - 48; c = getchar();}
    	return out * flag;
    }
    int pre[maxn],d[maxn],n,m;
    inline int find(int u){
    	if (u == pre[u]) return u;
    	int fa = find(pre[u]);
    	d[u] += d[pre[u]];
    	pre[u] = fa;
    	return fa;
    }
    void init(){
    	n = read(); m = read();
    	for (int i = 0; i <= n; i++) pre[i] = i,d[i] = 0;
    }
    int main()
    {
    	int T = read(),a,b,fa,fb,z;
    	bool flag;
    	while (T--){
    		init(); flag = true;
    		while (m--){
    			a = read() - 1; b = read(); z = read(); fa = find(a); fb = find(b);
    			if (fa != fb){
    				d[fa] = d[b] - d[a] - z;
    				pre[fa] = fb;
    			}else if (d[b] - d[a] != z) flag = false;
    		}
    		if (flag) printf("true
    ");
    		else printf("false
    ");
    	}
    	return 0;
    }
    


  • 相关阅读:
    [POJ3111]K Best(分数规划, 二分)
    [Python]实现简单决策树
    HDU 1269.迷宫城堡-Tarjan or 双向DFS
    HDU 2586.How far away ?-在线LCA(ST)-代码很认真的写了注释(捞到变形)
    HDU 5727.Necklace-二分图匹配匈牙利
    ZOJ 3593.One Person Game-扩展欧几里得(exgcd)
    牛客网 牛客小白月赛2 H.武-最短路(Dijkstra)
    牛客网 牛客小白月赛2 G.文
    牛客网 牛客小白月赛2 E.是是非非-尼姆博奕
    牛客网 牛客小白月赛2 D.虚虚实实-无向图判欧拉路径
  • 原文地址:https://www.cnblogs.com/Mychael/p/8282808.html
Copyright © 2011-2022 走看看