zoukankan      html  css  js  c++  java
  • [yLOI2018] 锦鲤抄

    先思考图上是\(tag\)的特殊情况。

    考虑我们按拓扑序反过来操作,就可以得到我们任意想要的顺序。

    那么我们把所有的图都缩点操作,那么我们只需要考虑一个联通分量里就行了。

    一个联通分量最后只会剩下一个不可取的,我们只要判断这个就可以了。

    那么按照权值大小排序,再一次判断是否可取即可。

    #include<iostream>
    #include<cstdio>
    #include<stack>
    #include<algorithm>
    #define ll long long 
    #define N 500004
    
    std::stack<int>QWQ;
    
    ll n,m,k;
    
    ll head[N],cnt,scc[N],siz[N],in[N];
    
    struct P{
    	int to,next;
    }e[N * 10];
    
    inline void add(int x,int y){
    	e[++cnt].to = y;
    	e[cnt].next = head[x];
    	head[x] = cnt;
    }
    
    struct E{
    	int w,id;
    }p[N];
    
    bool operator < (E a,E b){
    	return a.w > b.w;
    }
    
    ll dfn[N],low[N],vis[N],dfncnt,sccnt;
    
    inline void tarjan(ll u){
    	dfn[u] = low[u] = ++dfncnt;
    	QWQ.push(u);
    	vis[u] = 1;
    	for(int i = head[u];i;i = e[i].next){
    		int v = e[i].to;
    		if(!dfn[v]){
    			tarjan(v);
    			low[u] = std::min(low[u],low[v]);
    		}else if(vis[v]){
    			low[u] = std::min(low[u],dfn[v]);
    		}
    	}
    	if(dfn[u] == low[u]){
    		++sccnt;
    		while(QWQ.top() != u){
    			scc[QWQ.top()] = sccnt;
    			siz[sccnt] ++ ;
    			vis[QWQ.top()] = 0;
    			QWQ.pop();
    		}
    		siz[sccnt] ++ ;
    		scc[QWQ.top()] = sccnt;
    		vis[QWQ.top()] = 0;
    		QWQ.pop();
    	}
    }
    
    ll ans;
    
    int main(){
    	scanf("%lld%lld%lld",&n,&m,&k);
    	for(int i = 1;i <= n;++i)
    	scanf("%d",&p[i].w),p[i].id = i;
    	std::sort(p + 1,p + n + 1);
    	for(int i = 1;i <= m;++i){
    		ll x,y;
    		scanf("%lld%lld",&x,&y);
    		add(x,y);
    	}
    	for(int i = 1;i <= n;++i){
    		if(!dfn[i]){
    			tarjan(i);
    		}
    	}
    	for(int i = 1;i <= n;++i){
    		for(int j = head[i];j;j = e[j].next){
    			int v = e[j].to;
    			if(scc[v] != scc[i])
    			in[scc[v]] ++ ;
    		}
    	}
    	ll got = 0;
    	for(int i = 1;i <= n;++i){
    		int u = p[i].id;
    		if(in[scc[u]])
    		got ++ ,ans += p[i].w,siz[scc[u]] -- ;
    		else
    		if(siz[scc[u]] > 1)
    		got ++ ,ans += p[i].w,siz[scc[u]] -- ;
    		if(got == k)
    		break;
    	}
    	std::cout<<ans<<std::endl;
    }
    
  • 相关阅读:
    VMware虚拟机找不到USB设备该怎么办?
    关于Ubuntu锁屏后,无法输入密码
    设计模式-第一篇之单例模式
    Java-多线程第一篇多线程相关认识(1)
    Quartz-第二篇 使用quartz框架定时推送邮件
    Quartz-第一篇 认识Quartz
    Web Service-第一篇什么是Web Service
    Linux-第二篇常用命令
    Linux-第一篇linux基本认识
    Oracle-常见的错误
  • 原文地址:https://www.cnblogs.com/dixiao/p/15127286.html
Copyright © 2011-2022 走看看