题目传送门

我校神仙出的神仙题 \(\%\%\%\)


30分

找出所有有入度的点,排序,选前\(k\)个点,好了,30分到手。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define LL long long
using namespace std;
int read(){
    int k=0,f=1; char c=getchar();
    for(;c<'0'||c>'9';c=getchar())
      if(c=='-') f=-1;
    for(;c>='0'&&c<='9';c=getchar())
      k=k*10+c-48;
    return k*f;
}
int a[100010],sum,in[100010],b[100010],top;
bool cmp(int x,int y){
    return x > y;
}
int main(){
    int n=read(),m=read(),k=read();
    for(int i=1;i<=n;i++) a[i]=read();
    for(int i=1;i<=m;i++){
        int x=read(),y=read();
        in[y]++;
    }
    for(int i=1;i<=n;i++)
      if(in[i])  b[++top]=a[i];
    sort(b+1,b+top+1,cmp);
    for(int i=1;i<=k;i++) sum+=b[i];
    cout<<sum;
    return 0;
}

就这么简单
我跟你讲,这个做法以前是可以AC的

这个做法可以\(A\)掉\(DAG\)的\(Subtask\)
因为图是一个\(DAG\),所以对于所有有入度的点,一定可以将它们全部删去——从后向前删即可。既然所有有入度的点都能删去,我们只要贪心的取出前\(k\)大就好了。

AC

对于\(DAG\),一定可以将所有有入度的点全部删去,而普通有向图就不一样了——有环的存在

如上面\(4\)个点,它们形成了一个环,我们最多只能删掉\(3\)个。因为必定会有一个点被留下,所以我们贪心的留下点权最小的点。
但对环的讨论是十分繁琐的,我们可以先将整张图用\(Tarjan\)缩成一张\(DAG\),每个强连通分量内一定至少有一个环。对于强连通分量,我们分类讨论一下。

  • 对于缩点后有入度的强连通分量,十分显然,它内部的点我们可以随便选
  • 没有入度的强连通分量,我们必定要留下一个,理由如上所说。同理,我们贪心的留下点权最小的点即可。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int read(){
    int k=0; char c=getchar();
    for(;c<'0'||c>'9';) c=getchar();
    for(;c>='0'&&c<='9';c=getchar())
      k=k*10+c-48;
    return k;
}
struct zzz{
    int f,t,nex;
}e[2000010]; int head[500010],tot;
void add(int x,int y){
    e[++tot].t=y; e[tot].f=x;
    e[tot].nex=head[x];
    head[x]=tot;
}
struct hhh{
    int v,pos;
}a[500010];
int dfn[500010],low[500010],deep,vis[500010],colnum[500010],belong[500010],col,s[500010],top;
void Tarjan(int now){  //Tarjan缩点
    dfn[now]=low[now]=++deep; s[++top]=now; vis[now]=1;
    for(int i=head[now];i;i=e[i].nex){
        if(!dfn[e[i].t]){
            Tarjan(e[i].t);
            low[now]=min(low[now],low[e[i].t]);
        }
        else if(vis[e[i].t])
          low[now]=min(low[now],dfn[e[i].t]);
    }
    if(dfn[now]==low[now]){
        col++;
        int v=0;
        do{
            v=s[top--];
            vis[v]=0;
            colnum[col]++;
            belong[v]=col;
        }while(v!=now);
    }
}
int in[500010],ans;
bool cmp(hhh x,hhh y){
    return x.v < y.v;
}
bool cmp2(hhh x,hhh y){
    return x.v > y.v;
}
bool flag[500010],mapp[500010];
int main(){
    int n=read(),m=read(),k=read();
    for(int i=1;i<=n;i++)
      a[i].v=read(), a[i].pos=i;
    for(int i=1;i<=m;i++){
        int x=read(),y=read();
        add(x,y);
    }
    for(int i=1;i<=n;i++)
      if(!dfn[i]) Tarjan(i);
    memset(head,0,sizeof(head));
    for(int i=1;i<=tot;i++){  //缩点之后处理入度
        if(belong[e[i].f]!=belong[e[i].t])
          ++in[belong[e[i].t]];
    }
    //=======剔除入度为0的强联通分量里点权最小的点
    sort(a+1,a+n+1,cmp);
    for(int i=1;i<=n;i++){
        if(!in[belong[a[i].pos]]&&!flag[belong[a[i].pos]]){
            flag[belong[a[i].pos]]=1;
            mapp[a[i].pos]=1;
        }
    }
    int cnt=0;
    //=======贪心的从大到小选点
    sort(a+1,a+n+1,cmp2);
    for(int i=1;i<=n;i++){
        if(cnt==k) break;
        if(mapp[a[i].pos]) continue;
        ans+=a[i].v; cnt++;
    }
    cout<<ans;
    return 0;
}

在文章的最后,放一下官方题解,233~~~

Luogu P5008 逛庭院的更多相关文章

  1. 【洛谷P5008 逛庭院】tarjan缩点+贪心

    既然没有题解,那么我就来提供给一份. -- 首先我们看到数据范围.妈耶!数据这么大,一开始还想用个DP来做,但是看着就不行,那么根据这个数据范围,我们大致可以猜到这道题的算法是一个贪心,那么我们怎么贪 ...

  2. 【洛谷5008】逛庭院(Tarjan,贪心)

    [洛谷5008]逛庭院(Tarjan,贪心) 题面 洛谷 题解 如果图是一个\(DAG\),我们可以任意选择若干个不是入度为\(0\)的点,然后把它们按照拓扑序倒序删掉,不难证明这样一定是合法的. 现 ...

  3. [Luogu P3953] 逛公园 (最短路+拓扑排序+DP)

    题面 传送门:https://www.luogu.org/problemnew/show/P3953 Solution 这是一道神题 首先,我们不妨想一下K=0,即求最短路方案数的部分分. 我们很容易 ...

  4. 【luogu P3953 逛公园】 题解

    题目链接:https://www.luogu.org/problemnew/show/P3953 题外话:感觉2017年神题好多..这还不是最神的一道,真在考场上我也就写个最短路计数暴力了.现在在大佬 ...

  5. luogu 3953 逛公园

    noip2017 D1T3 逛公园 某zz选手看到数据范围直接就最短路计数了,结果写错了爆零 题目大意: N个点M条边构成的有向图,且没有自环和重边.其中1号点是起点,N号点是公园的终点,每条边有一个 ...

  6. Luogu P3953 逛公园(最短路+记忆化搜索)

    P3953 逛公园 题面 题目描述 策策同学特别喜欢逛公园.公园可以看成一张 \(N\) 个点 \(M\) 条边构成的有向图,且没有自环和重边.其中 \(1\) 号点是公园的入口,\(N\) 号点是公 ...

  7. luogu5008 逛庭院 (tarjan缩点)

    首先如果这是一个DAG,我按照拓扑序倒着去选,一定能选到所有入度不为0的点 然后考虑有环的情况 我们拎出来一个强连通分量 先假设它缩点以后是没有入度的 那我最后它里面一定至少剩一个不能选 因为就剩一个 ...

  8. Luogu P3953 逛公园

    不管怎么说,这都是一道十分神仙的NOIp题 你可以说它狗,但不可以否认它就是NOIp的难度 首先这道题很显然是道图论题还是一道图论三合一(最短路+拓扑+图上DP) 先考虑最短路,我们分别以\(1\)和 ...

  9. [luogu5008]逛庭院

    首先我们看到数据范围.妈耶!数据这么大,一开始还想用个DP来做,但是看着就不行,那么根据这个数据范围,我们大致可以猜到这道题的算法是一个贪心,那么我们怎么贪呢? 我们首先还是先画一个图: 样例解释一下 ...

随机推荐

  1. Miller-Rabin素性测试|Pollard's Rho算法

    Miller-Rabin 素性测试 Miller-Rabin 素数测试 一本通上的M-R不透彻啊~ Miller-Rabin是利用随机化算法判断一个数是合数还是素数. 首先,如果一个数N是素数,那么他 ...

  2. 「模拟赛20180307」三元组 exclaim 枚举+树状数组

    题目描述 给定 \(n,k\) ,求有多少个三元组 \((a,b,c)\) 满足 \(1≤a≤b≤c≤n\)且\(a + b^2 ≡ c^3\ (mod\ k)\). 输入 多组数据,第一行数据组数\ ...

  3. 解决Win10中vmware运行特别慢问题

    1.关闭防火墙:win+S打开搜索框,输入防火墙,选择windowsDefender防火墙 ,如图: 2.启用或关闭防火墙,如图: 3.关闭防火墙,两个选项都关闭,如图: 4.打开VMware,如果速 ...

  4. hive与hbase关联

    进入hbase: hbase shell 进入HIVE: hive hbase中建一张t_student_info表,添加两个列族 create 't_student_info','st1','st2 ...

  5. poj3254(状压dp入门第一道题,很详细)

    题目链接:http://poj.org/problem?id=3254 学习博客:https://blog.csdn.net/harrypoirot/article/details/23163485 ...

  6. Python 类总结

    Python可以继承多个父类,多重继承. 类支持多个对象的产生,命名空间的继承,运算符重载1).类产生多个实例对象Python OOP模型中的两种对象:类对象和实例对象.类对象提供默认的行为,是实例对 ...

  7. (转)diff 命令

    每天一个linux命令(36):diff 命令  原文:http://www.cnblogs.com/peida/archive/2012/12/12/2814048.html diff 命令是 li ...

  8. mysql双主互备

    mysql主从同步使得数据可以从一个数据库服务器复制到其他服务器上,在复制数据时,一个服务器充当主服务器(master),其余的服务器充当从服务器(slave),备服务器从主服务器同步数据,完成数据的 ...

  9. Java中的do-while循环——通过示例学习Java编程(11)

    作者:CHAITANYA SINGH 来源:https://www.koofun.com/pro/kfpostsdetail?kfpostsid=22&cid=0 在上一篇教程中,我们讨论了w ...

  10. JAVA中数组介绍

    一.数组: 数组指一组数据的集合,数组中的每个数据被称作元素. 二.数组定义: 数组类型[] 数组名 = new 数组类型[元素个数或数组长度]: (注意:等号前面的[]里面不能写任何东西) 也可以以 ...