Luogu P5008の散歩の庭

トピックポータル

質問のうち、私たちの学校の不滅の神々\(\%\%\%\)


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 \)\(サブタスク\)
グラフであるように(DAG \)\ので、度を有するすべての点について、これらはその全体を削除することができるようになる -から前方に削除することができます。すべてのポイントが度を削除することができているので、限り、我々貪欲取り外す前と\(K \)十分な大きさ。

交流

ため\(DAG \) 全ての削除のすべての点を有することができるようになり、通常の図と同じでありません-シクロアルキルの存在下で
5mMQ8n.png
上記のように(4 \)\点は、それらが環を形成します我々は削除することができます(3 \)\ヶ月。確かに私たちが貪欲な最小のポイント右のポイントを残したので、取り残されるのポイントが存在しますので。
しかし、リングの議論は、我々が最初に全体の見ることができ、非常に面倒です\(Tarjan \)収縮に\(DAG \)各強連結成分に少なくとも1つのリングを持っている必要があります。強連結成分のために、我々は、分類を議論します。

  • 強連結成分がポイント後の収縮の度合いを持っているために、非常に我々は任意のポイントを選ぶことができ、その中にそれをクリア
  • 強連結成分は学位ではない、我々は、上記の理由の1を残すことになるでしょう。同様に、我々は右のポイントに最小点を残して貪欲です。
#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

おすすめ

転載: www.cnblogs.com/morslin/p/11854928.html