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

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

小豆报名参加智力竞赛,他带上了n个好朋友作为亲友团一块来参加比赛。

比赛规则如下:

一共有m道题目,每个入都有1次答题机会,每次答题为选择一道题目回答,在回答正确后,可以从这个题目的后续题目,直达题目答错题目或者没有后续题目。每个问题都会代表一个价值,比赛最后的参赛选手获得奖励价值等价于该选手和他的亲友团没有回答的问题中的最低价值。我们现在知道小豆和他的亲友团实力非常强,能够做出这次竞赛中的所有题目。

小豆想知道在知道题目和后续题目的条件下,他最大能获得价值是多少?

原来两点可达的floyd求法是传递闭包啊……

我们floyd求出每个点之间是否可达,然后根据这个建边,之后跑一遍最小路径覆盖即可,答案为节点数-最大匹配数。

那么对答案二分,则只有两点都小于答案的点才可以连边,跑一遍即可。

#include<cmath>
#include<queue>
#include<cstdio>
#include<cctype>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=550;
const int M=N*N;
inline int read(){
    int X=0,w=0;char ch=0;
    while(!isdigit(ch)){w|=ch==‘-‘;ch=getchar();}
    while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
    return w?-X:X;
}
struct node{
    int to,nxt;
}e[M];
int vis[N],head[N],shu[N],cnt;
int w[N],mp[N][N],d[N][N],maxn,n,m;
inline void add(int u,int v){
    e[++cnt].to=v;e[cnt].nxt=head[u];head[u]=cnt;
}
bool dfs(int u,int id){
    for(int i=head[u];i;i=e[i].nxt){
    int v=e[i].to;
    if(vis[v]!=id){
        vis[v]=id;
            if(!shu[v]||dfs(shu[v],id)){
                shu[v]=u;
                return 1;
            }
    }
    }
    return 0;
}
inline void init(){
    cnt=0;
    memset(shu,0,sizeof(shu));
    memset(head,0,sizeof(head));
    memset(vis,0,sizeof(vis));
    memset(d,0,sizeof(d));
}
bool pan(int val){
    init();
    for(int i=1;i<=m;i++){
    for(int j=1;j<=m;j++){
        if(mp[i][j]&&w[i]<val&&w[j]<val)d[i][j]=1;
    }
    }
    for(int k=1;k<=m;k++){
    for(int i=1;i<=m;i++){
        if(!d[i][k])continue;
        for(int j=1;j<=m;j++){
        d[i][j]|=d[i][k]&d[k][j];
        }
    }
    }
    int ans=0;
    for(int i=1;i<=m;i++){
    if(w[i]<val)ans++;
    else continue;
    for(int j=1;j<=m;j++){
        if(d[i][j])add(i,j);
    }
    }
    for(int i=1;i<=m;i++){
    if(w[i]>=val)continue;
    if(dfs(i,i))ans--;
    }
    return ans<=n+1;
}
int main(){
    n=read(),m=read();
    for(int i=1;i<=m;i++){
    w[i]=read();int k=read();
    maxn=max(maxn,w[i]);
    for(int j=1;j<=k;j++){
        int v=read();
        mp[i][v]=1;
    }
    }
    for(int k=1;k<=m;k++){
    for(int i=1;i<=m;i++){
        if(!mp[i][k])continue;
        for(int j=1;j<=m;j++){
        if(i==j)continue;
        mp[i][j]|=mp[i][k]&mp[k][j];
        }
    }
    }
    int l=1,r=maxn+1;
    while(l<r){
    int mid=(l+r+1)>>1;
    if(pan(mid))l=mid;
    else r=mid-1;
    }
    if(l==maxn+1)puts("AK");
    else printf("%d\n",l);
    return 0;
}

+++++++++++++++++++++++++++++++++++++++++++

+本文作者:luyouqi233。               +

+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+

+++++++++++++++++++++++++++++++++++++++++++

原文地址:https://www.cnblogs.com/luyouqi233/p/9065606.html

时间: 2024-07-30 07:49:08

BZOJ5335:[TJOI2018]智力竞赛——题解的相关文章

bzoj5335: [TJOI2018]智力竞赛

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

TJOI2018 智力竞赛

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

[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个关卡中

《ACM国际大学生程序设计竞赛题解Ⅰ》——基础编程题

这个专栏开始介绍一些<ACM国际大学生程序设计竞赛题解>上的竞赛题目,读者可以配合zju的在线测评系统提交代码(今天zoj貌似崩了). 其实看书名也能看出来这本书的思路,就是一本题解书,简单暴力的通过题目的堆叠来提升解决编程问题的能力. 那么下面开始探索吧. zoj1037: BackgroundFor years, computer scientists have been trying to find efficient solutions to different computing p

竞赛题解 - Broken Tree(CF-758E)

Broken Tree(CF-758E) - 竞赛题解 贪心复习~(好像暴露了什么算法--) 标签:贪心 / DFS 『题意』 给出一棵以1为根的树,每条边有两个值:p-强度.w-重量. 对于给出的树,我们可以对每条边进行操作--将它的p.w同时减去相同的值,但是要求 \(p\ge0,w>0\) .(注意只能减,不能加) 进行操作后,需要使原树满足:如果 u 是 v 的父亲,那么 u 到 v 的边的 p 不能小于 以 v 为根节点的子树中所有边的 w 之和. 求出一种方案,使得在满足条件的情况下

BZOJ5334:[TJOI2018]数学计算——题解

https://www.lydsy.com/JudgeOnline/problem.php?id=5334 小豆现在有一个数x,初始值为1. 小豆有Q次操作,操作有两种类型: 1 m: x = x  *  m ,输出 x%mod; 2 pos: x = x /  第pos次操作所乘的数(保证第pos次操作一定为类型1,对于每一个类型1 的操作至多会被除一次),输出x%mod 都懒得写题解了……就对着时间建一个线段树,区间维护乘积即可. 真·大水题. #include<cmath> #inclu

电信学院第一届新生程序设计竞赛题解及std

首先非常感谢各位同学的参加,还有出题验题同学的辛勤付出 昨天想偷懒就是不想再把我C++11的想法改没了,大家看不懂的可以百度一下哦,懒得再写gcc了,毕竟代码是通的 题目类型一览 A Kannyi的数字密码 (模拟&&复杂的循环||手算)B Kannyi爱干净(注意变量初始化||set)C Kannyi的正方体和圆柱体(输入输出签到,PI已提示)D kannyi的独木桥(max和min)E Kannyi的简单检查 (循环签到 注意'-')F Kannyi的倒计时(a+b签到)G kanny

2016年浙江财经大学信工学院程序设计竞赛题解

代码为本人出于爱好 验题时所写,如有错误,敬请指出. 题面$pdf$为本人排版,不到之处,还请海涵.  联系方式$QQ$:$774388357$  浙江财经大学 $14$软件工程 周甄陶 正赛题面:https://pan.baidu.com/s/1jIQASxo 热身赛题面:https://pan.baidu.com/s/1mi4mjMg 热身赛$pdf$密码:IbcS3jJkkOsxiMCYfF6v 弱校现场赛$Rank$:https://pan.baidu.com/s/1kVBFGMV 热身