Test 6.29 T3 小学生

问题描述

“不错,不错!那么,准备好迎接下一道题了么?”一道白光闪过,CJK 眼前出现了 1e100 个小学生。“他们中,有一些人轨了我的机子。现在,我需要你在 1S 之内找出他们,并让他们认错!”凭借自己无所不知的神(xuan)奇(xue)力量, CJK 立刻发现了轨了 JesseLiun的机子的那 n 个小学生。但是,他还要想办法让小学生们认错。好在 CJK 有无穷多的糖,而有 p 个小学生愿意以一定的代价被收买。而小学生间有 r 个 BiShi 关系。一旦一个小学生被收买,他就会主动认错,并告发他 BiShi 的人,逼迫他们认错。那些被逼认错的人,也会告发他 BiShi 的人,以此类推。

输入格式

第一行两个数,n 和 p。紧接着 p 行,一行两个数 x 和 y,表示编号为 x 的小学生愿意以 y 的代价被收买。接下来一行是 m,紧跟着 m 行,每一行两个数字 x和 y,表示编号为 x 的小学生 BiShi 编号为 y 的小学生(当然,这并不意味着编号为 y 的会 BiShi 编号为 x 的)。

输出格式

如果 CJK 能让所有 n 个小学生认错,输出“YES”,并在下一行输出所需花费的最少糖果数。如果不能,输出“NO”,并在下一行输出编号最小的、且不会认错的小学生。

样例输入输出

样例输入1

3
2
1 10
2 100
2
1 3
2 3

样例输出1

YES
110

样例输入2

4
2
1 100
4 200
2
1 2
3 4

样例输出2

NO
3

解析

正解是Tarjan缩环,新点的权值为环上最小值,然后再DAG动态规划。一个点如果能被其他点达到的话,就没有必要选择这个点。

由于考场上忘了Tarjan,临时想出来一个做法,差不多就是先每个点跑一边DFS统计一个点可以由哪些点达到,然后和上面一样的逻辑,如果两个关键点可以互达说明有环,这时取最小值。否则则为能到达对方的点。

代码

#include <iostream>
#include <cstdio>
#include <cstring>
#define N 3002
#define M 20002
using namespace std;
int head[N],ver[M],nxt[M],l;
int m,n,p,w[N],i,j,f[N],g[N],a[N];
bool vis[N],e[N][N],key[N];
void insert(int x,int y)
{
    l++;
    ver[l]=y;
    nxt[l]=head[x];
    head[x]=l;
}
int min(int x,int y)
{
    if(w[x]<w[y]) return x;
    return y;
}
void dfs(int x,int node)
{
    vis[x]=1;
    for(int i=head[x];i;i=nxt[i]){
        int y=ver[i];
        if(!vis[y]){
            e[node][y]=1;
            dfs(y,node);
        }
    }
}
void dp(int x,int kid)
{
    if(vis[x]) return;
    vis[x]=1;
    if(f[x]==0) f[x]=kid;
    else if(e[kid][f[x]]&&!e[f[x]][kid]) f[x]=kid;
    else if(e[kid][f[x]]&&e[f[x]][kid]) f[x]=min(f[x],kid);
    for(int i=head[x];i;i=nxt[i]){
        int y=ver[i];
        if(f[y]!=kid) dp(y,kid);
    }
}
int main()
{
    freopen("pupil.in","r",stdin);
    freopen("pupil.out","w",stdout);
    cin>>n>>p;
    for(i=1;i<=p;i++){
        int x;
        cin>>a[i]>>x;
        w[a[i]]=x;
    }
    cin>>m;
    for(i=1;i<=m;i++){
        int u,v;
        cin>>u>>v;
        insert(u,v);
    }
    for(i=1;i<=n;i++) e[i][i]=1;
    for(i=1;i<=p;i++){
        memset(vis,0,sizeof(vis));
        dfs(a[i],a[i]);
    }
    for(i=1;i<=p;i++){
        memset(vis,0,sizeof(vis));
        dp(a[i],a[i]);
    }
    int ans=0;
    memset(vis,0,sizeof(vis));
    for(i=1;i<=n;i++){
        if(f[i]==0){
            cout<<"NO"<<endl<<i<<endl;
            return 0;
        }
        else if(!vis[f[i]]) ans+=w[f[i]],vis[f[i]]=1;
    }
    cout<<"YES"<<endl<<ans<<endl;
    fclose(stdin);
    fclose(stdout);
    return 0;
}

跑的贼慢......

原文地址:https://www.cnblogs.com/LSlzf/p/11111713.html

时间: 2024-11-06 03:45:54

Test 6.29 T3 小学生的相关文章

NOIP2017模拟赛 senior 6.29 T3 Gift(gift)

Description Input Output 这道题的难度相对来说并没有第二题恼火,但还是很难搞的. 那么这道题读完题目还是比较好看出这是一道背包的变形题. 因为每一份礼物都是取或者不取两个状态,所以,01背包好理解吧. 然后题目中说选到不能选为止,所以我们先将读入的礼物的价值排个序,然后从大到小我们去选取礼物,如果当前礼物价值大于剩余财富,那么我们就不能选了对吧. 于是就这样一层层的向下进行动归. 每一次我们处理当前层的DP数组,将答案加上上一层DP数组的值.这样我们就合理的处理完了整个D

Test 6.29 T3 简单数据结构练习

问题描述 费了一番功夫,神犇 CJK 终于完成了前三道题目."不错,不愧是新一代神犇啊!" JesseLiu 满意地说道,"不过,你在算法方面的功底固然不错.对于数据结构的运用,你又掌握地如何呢?" 听到"数据结构"这四个字,就连身为神犇的 CJK 也不禁吓出一身冷汗."年轻人,现在,对于我给定一棵树,你需要完成以下操作: 1.修改某个点的权值; 2.查询某两点间路径上所有点的权值和; 3.查询某点子树的权值和." CJK 脸

ViewPager,使用Fragment实现

效果如图: 使用Fragment实现tab的缺点就是不能够滑动.不过应该也算优点,具体场景可以自由选择. 完整代码:imooc-tab022fragment,在我的百度云网盘上. MainAcgtivity.java 1 package com.example.imooc_tab02; 2 3 import android.os.Bundle; 4 import android.support.v4.app.FragmentActivity; 5 import android.support.v

[JQuery]用InsertAfter实现图片走马灯展示效果2——js代码重构

写在前面 前面写过一篇文章<[JQuery]用InsertAfter实现图片走马灯展示效果>,自从写过那样的也算是使用面向对象的写法吧,代码实在丑陋,自从写过那样的代码,就是自己的一块心病,总感觉不完美,心里一直惦记着那件事,也是在我写过那篇文章之后,没多久,在博客园首页看到了一篇文章较复杂js的书写格式,这里的代码看着比较简介,就想着抽时间将之前的那段js代码进行重构.说做就做,不想一想起之前写过那样的代码,心里就有疙瘩.所以也就有了这篇文章. $.extend 在开始重构之前,需要先学习一

多线程并发练习(Day35)

练习一 #_*_coding:utf-8_*_ #!/usr/bin/env python import multiprocessing import threading import socket s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) s.bind(('127.0.0.1',8080)) s.listen(5) def action(conn): while True: data=conn.recv(1024) print(dat

python_day10

目录: 并发多线程 协程 I/O多路复用(未完成,待续) 一.并发多线程 1.线程简述: 一条流水线的执行过程是一个线程,一条流水线必须属于一个车间,一个车间的运行过程就是一个进程(一个进程内至少一个线程) 进程是资源单位 而线程才是cpu上的执行单位 2.线程的优点:共享资源.创建开销小 3.线程的模块开启方式之threading模块 multiprocess模块的完全模仿了threading模块的接口.执行如下图: 方式一: 函数式调用 1 from threading import Thr

[JQuery]用InsertAfter实现图片走马灯展示效果

写在前面 最近一个搞美工的朋友让我给他写一个图片轮播的特效. 需求: 图片向左循环滚动. 图片滚动到中间高亮显示,并在下方显示照片人物对应的信息. 鼠标悬停止滚动. 鼠标离开开始滚动. 单击图片,图片移到中间并高亮显示. 分析 思考一 首先想到的是图片轮播的插件,找了几款,并不是太满意,就放弃了. 思考二 然后想到使用jquery的animate()方法,对这个不熟悉,也放弃了. jQuery animate() 方法用于创建自定义动画. 语法 $(selector).animate({para

群众反映饮水问题被怼“不是人民” 当事官员被免

当然这个想法没有跟她们说不然两个铁定认为变态人尽有些变态想法嗯已经级了紫月洋洋自得笑道书生哥哥极冰匕的攻击力非常高紫月已经可以单挑级精英怪了 I am all impatience, Beltrami.The Marchese, I saw, was enjoying this conversation, as the subject-matter was of an involved and difficult character which appealed to the subtletie

使用std::mutex取代QMutex

为了保证对某个资源的操作是原子性的(对资源读写时,只有当前的操作结束,才允许另外线程对其操作,这里有个理解误区,资源操作原子性不是说,当前某个线程获得了某个资源使用权,然后线程执行时间完毕,要切换线程了,因为资源操作是原子性的,所以它就阻止线程切换,这是不可能的,要是某个程序里获得资源不放,那么操作系统上其他程序都不能跑咯.当然不是,原子操作的意思是,某个线程获得了某个资源的使用权,其他资源也想获得该资源的使用权时只能等待--等待会导致线程切换(节约CPU时间),只有当获得资源使用权的线程释放了