zoukankan      html  css  js  c++  java
  • luogu P5008 [yLOI2018] 锦鲤抄 |Tarjan

    简化版题意:

    给你一张有向图,每个点有一个点权。任意时刻你可以任意选择一个有入度的点,获得它的点权并把它和它的出边从图上删去。最多能选择 kkk 个点,求最多能获得多少点权。

    输入格式

    输入的第一行是三个用空格隔开的整数,代表图的点数 nnn 和边数 mmm 以及点数的限制 kkk。

    输入的第二行是 nnn 个用空格隔开的整数,第 iii 个数 wiw_iwi​ 代表点 iii 的火力值(点权)。

    第 333 到第 (m+2)(m + 2)(m+2) 行,每行两个用空格隔开的整数 u,vu, vu,v,代表一条 uuu 指向 vvv 的有向边。

    输出格式

    输出一行一个整数,代表最大的火力值。


    好题!!

    先缩点,然后分类讨论

    如果该强联通分量有入度,那可以全部都有机会被删

    如果没有,则必需留下一个点,那就把最小的留下,其他全部加进序列里来

    排序一下,取前k个

    #include<queue>
    #include<vector>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int N=5e5+10,M=2e6+10;
    int nxt[M],head[N],go[M],tot;
    inline void add(int u,int v){
    	nxt[++tot]=head[u],head[u]=tot,go[tot]=v;
    }
    inline int read(){
        int x=0,f=1; char ch=getchar();
        while(!isdigit(ch)) {if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch)) {x=x*10+ch-48;ch=getchar();}
        return x*f;
    }
    int n,m,k,a[N];
    vector<int>be[N];
    int dfn[N],low[N],co[N],st[N],top,num,col;
    void Tarjan(int u){
    	dfn[u]=low[u]=++num;
    	st[++top]=u;
    	for(int i=head[u];i;i=nxt[i]){
    		int v=go[i];
    		if(!dfn[v]){
    			Tarjan(v);
    			low[u]=min(low[u],low[v]);
    		}else if(!co[v])
    		low[u]=min(low[u],dfn[v]);
    	}
    	if(dfn[u]==low[u]){
    		co[u]=++col;
    		be[col].push_back(a[u]);
    		while(st[top]!=u){
    			co[st[top]]=col;
    			be[col].push_back(a[st[top]]);
    			--top;
    		}
    		--top;
    	}
    }
    vector<int>ans;
    struct node{
    	int u,v;
    }e[M];
    inline bool cmp(int x,int y){
    	return x>y;
    }
    int vis[N];
    signed main(){
    	n=read(),m=read(),k=read();
    	for(int i=1;i<=n;i++)a[i]=read();
    	for(int i=1,u,v;i<=m;i++){
    		u=read(),v=read();
    		e[i]=(node){u,v};
    		add(u,v);
    	}
    	for(int i=1;i<=n;i++)if(!dfn[i])Tarjan(i);
    	for(int i=1;i<=m;i++){
    		if(co[e[i].u]==co[e[i].v])continue;
    		vis[co[e[i].v]]=1;
    	}
    	for(int i=1;i<=col;i++){
    		if(vis[i])for(int j=0;j<be[i].size();j++)ans.push_back(be[i][j]);
    		else {
    			sort(be[i].begin(),be[i].end());
    			for(int j=1;j<be[i].size();j++)ans.push_back(be[i][j]);
    		}
    	}
    	sort(ans.begin(),ans.end(),cmp);
    	int res=0;
    	for(int i=0;i<k;i++)res+=ans[i];
    	cout<<res<<endl;
    }
    
  • 相关阅读:
    linux系统安装mysql数据库
    pyinstaller打包问题
    jmeter-Parameters和Body Data两种方式传参的区别
    jmeter-保存响应到文件
    Jenkins获取运行job的用户信息
    pytest插件(多重校验、用例依赖、执行顺序、失败重跑、重复执行、标记)
    谷歌开发者工具(F12)
    Linux常用命令
    一般什么原因会导致偶现问题?
    Fiddler模拟接口返回进行测试(二)
  • 原文地址:https://www.cnblogs.com/naruto-mzx/p/12712649.html
Copyright © 2011-2022 走看看