[TJOI 2018] 智力竞赛

[题目链接]

https://www.lydsy.com/JudgeOnline/problem.php?id=5335

[算法]

首先发现答案具有单调性 , 不妨二分答案mid

将所有权值小于mid的 , 且在原图上可以互相到达的点连边

那么我们需要判断新图的最小可重路径点覆盖是否 <= n + 1

直接网络流 / 匈牙利算法解决

时间复杂度 : O(M ^ 3logM)

[代码]

#include<bits/stdc++.h>
using namespace std;
#define N 510
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;

int n , m , len;
int w[N] , k[N] , a[N][N] , match[N] , vis[N] , b[N] , G[N][N] , mp[N][N];

template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); }
template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); }
template <typename T> inline void read(T &x)
{
    T f = 1; x = 0;
    char c = getchar();
    for (; !isdigit(c); c = getchar()) if (c == ‘-‘) f = -f;
    for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - ‘0‘;
    x *= f;
}
inline bool hungary(int u)
{
        for (int i = 1; i <= m; ++i)
        {
                if (G[u][i])
                {
                        if (!vis[i])
                        {
                                vis[i] = true;
                                if (!match[i] || hungary(match[i]))
                                {
                                        match[i] = u;
                                        return true;
                                }
                        }
                }
        }
        return false;
}
inline bool check(int mid)
{
        for (int i = 1; i <= m; ++i)
        {
                for (int j = 1; j <= m; ++j)
                {
                        G[i][j] = 0;
                }
        }
        for (int i = 1; i <= m; ++i)
        {
                for (int j = 1; j <= m; ++j)
                {
                        if (w[i] < mid && w[j] < mid && mp[i][j])
                                G[i][j] = 1;
                }
        }
        for (int x = 1; x <= m; ++x)
        {
                for (int i = 1; i <= m; ++i)
                {
                        if (!G[i][x]) continue;
                        for (int j = 1; j <= m; ++j)
                        {
                                if (i != j)
                                        G[i][j] |= (G[i][x] & G[x][j]);
                        }
                }
        }
        int res = 0;
        for (int i = 1; i <= m; ++i)
                if (w[i] < mid) ++res;
        for (int i = 1; i <= m; ++i) match[i] = vis[i] = 0;
        for (int i = 1; i <= m; ++i)
        {
                memset(vis , false , sizeof(vis));
                if (w[i] < mid && hungary(i))
                        --res;
        }
        return res <= n + 1;
}

int main()
{

        read(n); read(m);
        for (int i = 1; i <= m; ++i)
        {
                read(w[i]);
                read(k[i]);
                for (int j = 1; j <= k[i]; ++j)
                {
                        read(a[i][j]);
                        mp[i][a[i][j]] = true;
                }
                b[i] = w[i];
        }
        for (int x = 1; x <= m; ++x)
        {
                for (int i = 1; i <= m; ++i)
                {
                        if (!mp[i][x]) continue;
                        for (int j = 1; j <= m; ++j)
                        {
                                if (i != j)
                                        mp[i][j] |= (mp[i][x] & mp[x][j]);
                        }
                }
        }
        sort(b + 1 , b + m + 1);
        int l = 1 , r = m , ans = 0;
        while (l <= r)
        {
                int mid = (l + r) >> 1;
                if (check(b[mid]))
                {
                        ans = b[mid];
                        l = mid + 1;
                } else r = mid - 1;
        }
        if (check(b[m] + 1)) printf("AK\n");
        else printf("%d\n" , ans);

        return 0;

}

原文地址:https://www.cnblogs.com/evenbao/p/10544873.html

时间: 2024-08-29 17:57:52

[TJOI 2018] 智力竞赛的相关文章

[Offer收割]编程练习赛3 - 题目3 : 智力竞赛

智力竞赛 Problem's Link ---------------------------------------------------------------------------- Mean: 略(中文题). analyse: 比赛中最先想到的是三维dp,但思考后发现可以压缩为二维,状态转移方程: dp[i][j]=min(dp[i][j],dp[i][j-(right+fault)]+right) 其中dp[i][j]表示: 到通过第i关为止,在总共只有j次答题机会的情况下,总共至

hihocoder #1285 智力竞赛

传送门 总结: 1.仔细读题 2.仔细分析复杂度 3.不要想当然,乱下结论 时间限制:5000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi.小Ho还有被小Hi强拉来的小Z,准备组队参加一个智力竞赛.竞赛采用过关制,共计N个关卡.在第i个关卡中,小Hi他们需要获得Ai点分数才能够进入下一关.每一关的分数都是独立计算的,即使在一关当中获得超过需要的分数,也不会对后面的关卡产生影响. 小Hi他们可以通过答题获得分数.答对一道题获得S点分数,答错一道题获得T点分数.在所有的N个关卡中

BZOJ5335:[TJOI2018]智力竞赛——题解

https://www.lydsy.com/JudgeOnline/problem.php?id=5335 小豆报名参加智力竞赛,他带上了n个好朋友作为亲友团一块来参加比赛. 比赛规则如下: 一共有m道题目,每个入都有1次答题机会,每次答题为选择一道题目回答,在回答正确后,可以从这个题目的后续题目,直达题目答错题目或者没有后续题目.每个问题都会代表一个价值,比赛最后的参赛选手获得奖励价值等价于该选手和他的亲友团没有回答的问题中的最低价值.我们现在知道小豆和他的亲友团实力非常强,能够做出这次竞赛中

TJOI2018 智力竞赛

这题做的真的让我没了智力... 题目大意: 从n个点的图中选出n + 1条链问是否能够全部覆盖(可相交),如果不能,输出覆盖的最小点权最小值最大是多少? 思路: 最小值最大问题考虑二分,二分答案用二分图匹配去求链覆盖即可,记得floyd处理闭包. 吐槽: 调了半天发现是二分上界太大...wtf? Code: #include <bits/stdc++.h> using namespace std; const int MAXN = 510; const int INF = 1e9; int v

bzoj5335: [TJOI2018]智力竞赛

这道题做了一个多月?感谢噶爷教我做题 (滑稽)自己给自己停bc准备中考然而还是考的不咋地 这道题二分之后就是找最小链覆盖,算经典的吧. 注意下那个权可能重复啊,二分要离散化..(然而我WA无数次的原因居然是打了个match[y]==false什么鬼) #include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #includ

都怪当初看了这6段代码,造成了如今的深度学习!

回忆当初我们看到的这6段代码,造就了我们如今的深度学习,这6段代码的创作者及其取得 的这些辉煌成就的那些故事.这些故事都对应的有简单的代码示例,小伙伴们在FloydHub 和 GitHub 上找到相关代码. 提示一下:要运行 FloydHub 上的代码,需要确保你的电脑上已经安装了Floyd命令工具,并且复制代码保存到本地计算机.在本地计算机示例项目中初始化命令行界面之后,您就可以运行以下命令在 FloydHub 上启动项目: 最小二乘法 所有的深度学习算法都始于下面这个数学公式(我已将其转成

IBM的淘汰之路

BM曾经在计算领域独领风骚,但是90年被PC产业链上的微软.英特尔等厂商围殴,遭遇最严重的危机; 今天在云计算市场,IBM曾在遭遇同样的危机,这一次不知道它能否安然度过; IBM收购红帽转向混合云,是硬件厂商做公有云失败的最新案例,因为硬件厂商并不懂云计算; 百年企业面对如今快速变化的时代,已经有很多倒下了,柯达.诺基亚 -- 下一个会是IBM吗? 踏准每一个浪潮,是任何一家科技企业都梦寐以求的事. 但现实是,多数企业的寿命抵不过一次技术发展的周期.<财富>杂志的统计显示,全球"50

luogu 乘积最大

题目描述 今年是国际数学联盟确定的"2000――世界数学年",又恰逢我国著名数学家华罗庚先生诞辰90周年.在华罗庚先生的家乡江苏金坛,组织了一场别开生面的数学智力竞赛的活动,你的一个好朋友XZ也有幸得以参加.活动中,主持人给所有参加活动的选手出了这样一道题目: 设有一个长度为N的数字串,要求选手使用K个乘号将它分成K+1个部分,找出一种分法,使得这K+1个部分的乘积能够为最大. 同时,为了帮助选手能够正确理解题意,主持人还举了如下的一个例子: 有一个数字串:312, 当N=3,K=1时

2000年 乘积最大

乘积最大 题目描述 今年是国际数学联盟确定的“2000——世界数学年”,又恰逢我国著名数学家华罗庚先生诞辰90周年.在华罗庚先生的家乡江苏金坛,组织了一场别开生面的数学智力竞赛的活动,你的一个好朋友XZ也有幸得以参加.活动中,主持人给所有参加活动的选手出了这样一道题目: 设有一个长度为N的数字串,要求选手使用K个乘号将它分成K+1个部分,找出一种分法,使得这K+1个部分的乘积能够为最大. 同时,为了帮助选手能够正确理解题意,主持人还举了如下的一个例子: 有一个数字串:312, 当N=3,K=1时