zoukankan      html  css  js  c++  java
  • P5008 [yLOI2018] 锦鲤抄(Tarjan+贪心)

    洛谷

    题意:
    给出一个有向图,每次可以删除存在入度的点及其出边,每次删除一个点可以获得其权值。
    问最终能够获得的最大权值为多少。

    思路:
    考虑DAG:我们直接倒着拓扑序来选,即可将所有入度不为(0)的点选完。
    若不为DAG,考虑(tarjan)求出强连通分量,分析可以发现:对于一个单独的强连通分量,假设其点数为(n),那么可以选择(n-1)个点;若其入度不为(0),那么强连通分量中所有点都可以选择。
    然后直接这样来搞就行。
    证明...我也不会,在纸上画画就行了。

    #include <bits/stdc++.h>
    #define MP make_pair
    #define fi first
    #define se second
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    #define INF 0x3f3f3f3f
    // #define Local
    #ifdef Local
      #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
      void err() { std::cout << '
    '; }
      template<typename T, typename...Args>
      void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
    #else
      #define dbg(...)
    #endif
    void pt() {std::cout << '
    '; }
    template<typename T, typename...Args>
    void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    //head
    const int N = 5e5 + 5, M = 2e6 + 5;
    
    struct Edge{
    	int v, next;
    }e[M];
    int a[N];
    int head[N], tot;
    void adde(int u, int v) {
    	e[tot].v = v; e[tot].next = head[u]; head[u] = tot++;
    }
    int n, m, k;
    pii E[M];
    
    stack <int> s;
    int T, num;
    int col[N], dfn[N], low[N], Min[N];
    bool chk[N];
    void Tarjan(int u){
        dfn[u] = low[u] = ++T; 
        s.push(u);
        for(int i = head[u]; i != -1;i = e[i].next){
            int v = e[i].v;
            if(!dfn[v]){
                Tarjan(v);
                low[u] = min(low[u], low[v]);
            }else if(!col[v]){
                low[u] = min(low[u], dfn[v]);
            }
        }
        if(low[u] == dfn[u]){
            num++; int now;
            do{
                now = s.top(); s.pop();
                col[now] = num;
                Min[num] = min(Min[num], a[now]);
            }while(!s.empty() && now!=u);
        }
    }
    int in[N];
    void run() {
    	cin >> n >> m >> k;
    	memset(head, -1, sizeof(head)); tot = 0;
    	memset(Min, INF, sizeof(Min));
    	ll ans = 0;
    	for(int i = 1; i <= n; i++) cin >> a[i];
    	for(int i = 1; i <= m; i++) {
    		int u, v; cin >> u >> v;
    		E[i] = MP(u, v);
    		adde(u, v);
    	}
    	for(int i = 1; i <= n; i++) {
    		if(!dfn[i]) Tarjan(i);
    	}
    	for(int i = 1; i <= m; i++) {
    		int u = E[i].fi, v = E[i].se;
    		if(col[u] != col[v]) ++in[col[v]];
    	}
    	for(int i = 1; i <= n; i++) {
    		int bel = col[i];
    		if(a[i] == Min[bel] && in[bel] == 0) {
    			if(!chk[bel]) {
    				chk[bel] = 1;
    				a[i] = 0;
    			}
    		} 
    	}
    	sort(a + 1, a + n + 1); reverse(a + 1, a + n + 1);
    	for(int i = 1; i <= k; i++) ans += a[i];
    	pt(ans);
    }
    
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
    #ifdef Local
        freopen("../input.in", "r", stdin);
        freopen("../output.out", "w", stdout);
    #endif
        run();
        return 0;
    }
    
  • 相关阅读:
    lsmod-查看内核模块信息
    centos 7 下通过 conda 安装 cuda pytorch
    python 中文编码
    matplotlib
    How to determine the correct number of epoch during neural network training? 如何确定Epoch
    nvidia-smi Failed to initialize NVML: Driver/library version mismatch
    MySQL MAX函数:查询指定列的最大值
    mysql之group_concat函数详解
    @Param注解的用法解析@Param注解的用法解析
    【MySQL函数】replace()函数
  • 原文地址:https://www.cnblogs.com/heyuhhh/p/11717068.html
Copyright © 2011-2022 走看看