首页 > 其他分享 >P1525 [NOIP2010 提高组] 关押罪犯

P1525 [NOIP2010 提高组] 关押罪犯

时间:2024-03-25 20:45:24浏览次数:34  
标签:P1525 二分 阈值 关押 int NOIP2010 罪犯 include 监狱

带权并查集中,dist[]数组可以理解为一个向量,这样子比按照距离来理解更透彻:

优秀学习资料:

AcWing 240. 食物链(带权并查集) - AcWing

即d[a]表示向量a->fa[a]

这道题的并查集解法:

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string>
#include <cmath>
#define For(i, j, n) for (int i = j; i <= n; ++i)
using namespace std;

const int N = 20005, M = 100005;

int fa[N], d[N];
int n, m;
struct _edges
{
    int a, b, w;
    bool operator<(const _edges &t) const
    {
        return w > t.w;
    }
} Edge[M];

void init(int n)
{
    for (int i = 1; i <= n; i++)
        fa[i] = i;
}

int find(int a)
{
    if (a == fa[a])
        return a;
    int old_fa = fa[a];
    fa[a] = find(old_fa);
    d[a] = (d[a] + d[old_fa]) % 2;
    return fa[a];
}

int solve()
{
    for (int i = 1; i <= m + 1; i++)
    {
        int a = Edge[i].a, b = Edge[i].b;
        int x = find(a), y = find(b);
        if (x != y)
        {
            d[x] = (d[b] - d[a] + 3) % 2;
            fa[x] = y;
           // printf("D %d %d %d %d %d\n", a, b, x, y, d[x])
        }
        else
        {
            if((d[a] - d[b] + 2) % 2 == 0)
                return Edge[i].w;
        }
    }
    return 0;
}

int main()
{
    scanf("%d%d", &n, &m);
    init(n);
    int a, b, w;
    for (int i = 1; i <= m; i++)
    {
        scanf("%d%d%d", &a, &b, &w);
        Edge[i] = {a, b, w};
    }
    Edge[m + 1] = {0, 0, 0};
    sort(Edge + 1, Edge + m + 1);
    cout << solve();
    return 0;
}

一开始把贪心想错了,把所有节点联通之后才开始计算答案,实际上,在整棵树连通之前,可能就已经有节点通过前面的边间接确定了关系,这时候它们就不得不分配在同一个监狱了,此时已经可以返回答案了。

解法二:

二分+二分图,二分一个权值的阈值,超过这个阈值的边,就把它们连起来,如果能够建立二分图(用二分图判定定理判断),就说明这个阈值还能够提高

这里边的实际含义相当于“不能住在同一个监狱”,如果能建立二分图的话,两个集合就分别表示两个监狱。边只存在于两个集合之间,而不存在于集合内部,现实含义就是:

监狱一和监狱二中的罪犯之间都不能住在一起,而集合内部没有边,即同一个监狱的罪犯都住在一起。

 

标签:P1525,二分,阈值,关押,int,NOIP2010,罪犯,include,监狱
From: https://www.cnblogs.com/smartljy/p/18095287

相关文章

  • 洛谷题单指南-集合-P1525 [NOIP2010 提高组] 关押罪犯
    原题链接:https://www.luogu.com.cn/problem/P1525题意解读:有很多罪犯,要关到两座监狱,有一些罪犯之间有仇,并且可以量化出仇恨值,如果关在一起就会冲突,造成的影响就是仇恨值,要使得造成的影响最小,如果可以完全不起冲突,输出0。解题思路:首先,要让冲突影响最小化,显然应该把仇恨大的罪犯......
  • 洛谷题单指南-线性表-P1540 [NOIP2010 提高组] 机器翻译
    原题链接:https://www.luogu.com.cn/problem/P1540题意解读:本题模拟内存的调入调出,内存先入先出的特性就是队列。解题思路:本题需要两种数据结构:队列、数组队列用来模拟内存的操作,数组充当hash表用于判断单词在内存是否存在核心逻辑:对于每一个单词,如果内存不存在,查一次词典,再将......
  • P1525 [NOIP2010 提高组] 关押罪犯
    原题链接题解1:按边权从大到小排序,如果这条边的两个点没确定关系,那么把他们设为敌人这样,就成了一棵棵最大生成树(因为有的罪犯之间没有怨气)由敌人的敌人是朋友可以得出,如果两个点在同一棵树,且距离为偶数,那么代表他们之间互为朋友code1#include<bits/stdc++.h>usingnamespace......
  • P1541 [NOIP2010 提高组] 乌龟棋题解
    有两种方法,代码注释都很详细了直接上代码一:记忆化搜索#include<bits/stdc++.h>usingnamespacestd;intt[15];intn,m;inta[400];intmp[45][45][45][45];//mp[i][j][k][l]表示1号用i张,2号用j张,3号用k张,4号用l张的情况下,最多能拿多少分intdfs(intstep,intw)//step......
  • [NOIP2010 提高组] 关押罪犯 - 洛谷
    P1525[NOIP2010提高组]关押罪犯-洛谷|计算机科学教育新生态(luogu.com.cn)种类并查集#include<bits/stdc++.h>#definedebug(a)cout<<#a<<"="<<a<<'\n';usingnamespacestd;usingi64=longlong;typedefpair<i64,i64>......
  • P1525 [NOIP2010 提高组] 关押罪犯
    P1525[NOIP2010提高组]关押罪犯法一:二分图把犯人分配到两个监狱,使得监狱内的怒气值最大最小分配到两个集合中,考虑二分染色分析因为答案具有单调性所以可以二分:判断x是否符合,只需要重建大于x的边,如果不能把它们分到两个集合中(二分染色失败),就往上调(考虑无限大,那么就不矛盾)......
  • [NOIP2010 提高组] 乌龟棋
    题目背景小明过生日的时候,爸爸送给他一副乌龟棋当作礼物。题目描述乌龟棋的棋盘是一行NN个格子,每个格子上一个分数(非负整数)。棋盘第11格是唯一的起点,第NN格是终点,游戏要求玩家控制一个乌龟棋子从起点出发走到终点。乌龟棋中MM张爬行卡片,分成44种不同的类型(MM张......
  • P1540 [NOIP2010 提高组] 机器翻译
    传送门题目背景小晨的电脑上安装了一个机器翻译软件,他经常用这个软件来翻译英语文章。题目描述这个翻译软件的原理很简单,它只是从头到尾,依次将每个英文单词用对应的中文含义来替换。对于每个英文单词,软件会先在内存中查找这个单词的中文含义,如果内存中有,软件就会用它进行翻译;......
  • P1514 [NOIP2010 提高组] 引水入城
    link搜索。首先先用\(dfs\)判断一下对于每一个点来说对应的可以覆盖的\(L,R\).假设题目一定存在一个解,所以一定会有该点覆盖的区间连续。设该区间为\(L,R\),若不是每一个点均会被覆盖,那么题目不会存在任何一个解。判断是否有解:跑一遍\(dfs\),记录每一个点被\(dfs......
  • 「NOIP2010」机器翻译 题解
    前言附加任务这道题也是一个简单模拟题。传送门解析这道题就是一个简单的模拟题,简单来说就是如果内存里面没有这个单词(其实是一个数)的话就从外存入队,如果内存容量不够,出队即可。对了,每次查询时还要计数噢!代码话不多说上代码#include<bits/stdc++.h>usingnamespacestd......