zoukankan      html  css  js  c++  java
  • P5008[yLOI2018]锦鲤抄【tarjan】

    正题

    题目链接:https://www.luogu.com.cn/problem/P5008


    题目大意

    给出\(n\)个点\(m\)条边的一张有向无环图,你每次可以选择一个有入度的点获取其点权然后删除这个点。求能取\(k\)次的情况下最大能获得的权值和。

    \(1\leq n\leq 5\times 10^5+4,1\leq m\leq 2\times 10^6+4\)


    解题思路

    先考虑\(DAG\)怎么做,很显然的我们可以通过调整选择顺序做到只有入度为\(0\)的点不能选择,其他都任意选择。

    然后如果有强连通分量的话,同理我们考虑一个环,发现环上只有一个点不能够被选择,而如果这个环本身就有一个入度那么显然所有点都可以任意选择。

    而如果是入度为\(0\)的强连通我们直接删掉权值最小的点不能选择就好了。

    然后排序乱选。

    时间复杂度:\(O(n\log n+m)\)


    code

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<stack>
    using namespace std;
    const int N=5e5+10,M=2e6+10;
    struct node{
    	int to,next;
    }a[M];
    int n,m,k,tot,cnt,ans,in[N],w[N],v[N];
    int d[N],col[N],ls[N],dfn[N],low[N];
    bool ins[N];stack<int> s;
    void addl(int x,int y){
    	a[++tot].to=y;
    	a[tot].next=ls[x];
    	ls[x]=tot;return;
    }
    void tarjan(int x){
    	dfn[x]=low[x]=++cnt;
    	ins[x]=1;s.push(x);
    	for(int i=ls[x];i;i=a[i].next){
    		int y=a[i].to;
    		if(!dfn[y]){
    			tarjan(y);
    			low[x]=min(low[x],low[y]);
    		}
    		else if(ins[y])
    			low[x]=min(low[x],dfn[y]);
    	}
    	if(dfn[x]==low[x]){
    		while(s.top()!=x){
    			w[x]=min(w[x],w[s.top()]);
    			col[s.top()]=x;ins[s.top()]=0;
    			s.pop();
    		}
    		col[x]=x;ins[x]=0;s.pop();
    	}
    	return;
    }
    int main()
    {
    	scanf("%d%d%d",&n,&m,&k);
    	for(int i=1;i<=n;i++)
    		scanf("%d",&w[i]),v[i]=w[i];
    	for(int i=1,x,y;i<=m;i++)
    		scanf("%d%d",&x,&y),addl(x,y);
    	for(int i=1;i<=n;i++)
    		if(!dfn[i])tarjan(i);
    	for(int x=1;x<=n;x++)
    		for(int i=ls[x];i;i=a[i].next){
    			int y=a[i].to;
    			if(col[x]==col[y])continue;
    			in[col[y]]++;
    		}
    	int _=0;
    	for(int i=1;i<=n;i++)
    		if(col[i]==i&&!in[i])d[++_]=w[i];
    	sort(d+1,d+1+_);sort(v+1,v+1+n);
    	for(int i=n;i>=1;i--){
    		if(d[_]==v[i]){_--;continue;}
    		k--;ans+=v[i];
    		if(!k)break;
    	}
    	printf("%d\n",ans);
    	return 0;
    }
    
  • 相关阅读:
    如何在Elasticsearch中解析未分配的分片(unassigned shards)
    spark-streaming获取kafka数据的两种方式
    hbase读写优化
    手动修复 under-replicated blocks in HDFS
    kubectl常用命令(个人记录)
    mysql远程访问被拒绝问题
    海盗分金问题
    《转》基于OpenCV的傅里叶变换及逆变换
    char*,string和CString之间的转换
    commons-fileupload 核心API 分析
  • 原文地址:https://www.cnblogs.com/QuantAsk/p/15413341.html
Copyright © 2011-2022 走看看