zoukankan      html  css  js  c++  java
  • luogu5008 逛庭院 (tarjan缩点)

    首先如果这是一个DAG,我按照拓扑序倒着去选,一定能选到所有入度不为0的点

    然后考虑有环的情况 我们拎出来一个强连通分量 先假设它缩点以后是没有入度的

    那我最后它里面一定至少剩一个不能选 因为就剩一个的时候肯定没有入度呀

    那我显然可以把它看成是一个只有一个点入度为0的DAG 而且那个入度为0的点可以任选 那就是刚才的结论了

    如果它缩点以后有入度 那它就整个都能选了

    所以就缩点以后把每个入度为0的点内权值最小的那个去掉 最后取前k大的就行了

    这里有一个trick:可以用nth_element找到第k大 然后扫一遍把所有大于它的都加上,是O(n)的

    然而并不需要2333

     1 #include<bits/stdc++.h>
     2 #define CLR(a,x) memset(a,x,sizeof(a))
     3 using namespace std;
     4 typedef long long ll;
     5 typedef pair<int,int> pa;
     6 const int maxn=5e5+10,maxm=2e6+10;
     7 
     8 inline ll rd(){
     9     ll x=0;char c=getchar();int neg=1;
    10     while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
    11     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
    12     return x*neg;
    13 }
    14 
    15 int eg[maxm][2],egh[maxn],ect;
    16 int N,M,K,dfn[maxn],tot,low[maxn],stk[maxn],sh,bel[maxn],pct;
    17 int lst[maxn],v[maxn];
    18 bool instk[maxn],ine[maxn];
    19 
    20 inline void adeg(int a,int b){
    21     eg[++ect][0]=b,eg[ect][1]=egh[a],egh[a]=ect;
    22 }
    23 
    24 void tarjan(int x){
    25     dfn[x]=low[x]=++tot;
    26     instk[x]=1,stk[++sh]=x;
    27     for(int i=egh[x];i;i=eg[i][1]){
    28         int b=eg[i][0];
    29         if(!dfn[b]) tarjan(b),low[x]=min(low[x],low[b]);
    30         else if(instk[b]) low[x]=min(low[x],dfn[b]);
    31     }
    32     if(low[x]==dfn[x]){
    33         ++pct;
    34         int mi=23333;
    35         while(1){
    36             bel[stk[sh]]=pct;
    37             instk[stk[sh]]=0;
    38             if(v[stk[sh]]<mi) mi=v[stk[sh]],lst[pct]=stk[sh];
    39             if(stk[sh--]==x) break;
    40         }
    41     }
    42 }
    43 
    44 int main(){
    45     //freopen("","r",stdin);
    46     int i,j,k;
    47     N=rd(),M=rd(),K=rd();
    48     for(i=1;i<=N;i++) v[i]=rd();
    49     for(i=1;i<=M;i++){
    50         int a=rd(),b=rd();
    51         adeg(a,b);
    52     }
    53     for(i=1;i<=N;i++)
    54         if(!dfn[i]) tarjan(i);
    55     for(i=1;i<=N;i++){
    56         for(j=egh[i];j;j=eg[j][1]){
    57             if(bel[eg[j][0]]!=bel[i])
    58                 ine[bel[eg[j][0]]]=1;
    59         }
    60     }
    61     for(i=1;i<=pct;i++){
    62         if(!ine[i]) v[lst[i]]=0;
    63     }
    64     sort(v+1,v+N+1);
    65     int ans=0;
    66     for(i=N;i>=N-K+1;i--)
    67         ans+=v[i];
    68     printf("%d
    ",ans);
    69     return 0;
    70 }
  • 相关阅读:
    安卓AlertDialog的使用
    蚂蚁的腿
    年龄排序
    Digital Roots
    小明的存钱计划
    不高兴的小明
    管闲事的小明
    小明的调查作业
    爱摘苹果的小明
    小明的难题
  • 原文地址:https://www.cnblogs.com/Ressed/p/9911824.html
Copyright © 2011-2022 走看看