zoukankan      html  css  js  c++  java
  • LGOJP4381 [IOI2008]Island

    题目链接

    https://www.luogu.org/problem/P4381

    题解

    基环树直径的板子。但是dfs会爆栈...所以最后改成了bfs。还是一个很考验码力的板子。
    首先基环树的直径显然有两种情况,在不进入环的情况下在一个子树内,这直接dp求就好了。第二种是一个子树中的链+环上一段+另外一个子树中的链。按这两种情况分类讨论即可。对于这种情况,可以在先求第一种情况的同时把子树中的以子树的根为起点的最长链求出来,然后拓扑排序找出环,处理出环上的前缀和,断环成链,在上面跑一下单调队列就可以求出第二种情况下的(max)了。然后这道题里这些步骤最好都是用bfs实现,dfs可能会爆栈...各种细节也要注意好...复杂度是(O(n))的。

    #include <bits/stdc++.h>
    using namespace std;
    
    namespace io {
    char buf[1<<21], *p1 = buf, *p2 = buf;
    inline char gc() {
        if(p1 != p2) return *p1++;
        p1 = buf;
        p2 = p1 + fread(buf, 1, 1 << 21, stdin);
        return p1 == p2 ? EOF : *p1++;
    }
    #define G gc
    
    #ifndef ONLINE_JUDGE
    #undef G
    #define G getchar
    #endif
    
    template<class I>
    inline void read(I &x) {
        x = 0; I f = 1; char c = G();
        while(c < '0' || c > '9') {if(c == '-') f = -1; c = G(); }
        while(c >= '0' && c <= '9') {x = x * 10 + c - '0'; c = G(); }
        x *= f;
    }
    template<class I>
    inline void write(I x) {
        if(x == 0) {putchar('0'); return;}
        I tmp = x > 0 ? x : -x;
        if(x < 0) putchar('-');
        int cnt = 0;
        while(tmp > 0) {
            buf[cnt++] = tmp % 10 + '0';
            tmp /= 10;
        }
        while(cnt > 0) putchar(buf[--cnt]);
    }
    
    #define in(x) read(x)
    #define outn(x) write(x), putchar('
    ')
    #define out(x) write(x), putchar(' ')
    
    } using namespace io;
    
    #define ll long long
    const int N = 1000100;
    
    deque<int>q;
    int n, b[N], tot, in[N];
    int head[N], cnt = 1, vis[N * 2];
    int Ctot, c[N], a[N * 2];
    struct edge {
    	int to, nxt;
    	int v;
    } e[N << 1];
    ll ans = 0, now = 0, s[N * 2], f[N * 2], d[N];
    
    void ins(int u, int v, int w) {
    	e[++cnt] = (edge) {v, head[u], w};
    	head[u] = cnt;
    }
    
    void bfs(int S, int bl) {
    	c[S] = bl;
    	q.clear(); q.push_back(S);
    	while(!q.empty()) {
    		int u = q.front(); q.pop_front();
    		c[u] = bl;
    		for(int i = head[u]; i; i = e[i].nxt) {
    			int v = e[i].to;
    			if(!c[v]) q.push_back(v);
    		}
    	}
    }
    
    void topsort() {
    	q.clear();
    	for(int i = 1; i <= n; ++i) {
    		if(in[i] == 1) q.push_back(i);
    	}
    	while(!q.empty()) {
    		int u = q.front(); q.pop_front();
    		for(int i = head[u]; i; i = e[i].nxt) {
    			int v = e[i].to;
    			if(in[v] > 1) {
    				d[c[u]] = max(d[c[u]], f[u] + f[v] + e[i].v);
    				f[v] = max(f[v], f[u] + e[i].v);
    				--in[v]; if(in[v] == 1) q.push_back(v);
    			}
    		}
    	}
    }
    
    void dp(int S, int vc) {
    	int tot = 0, u = S;
    	a[++tot] = u;
    	while(1) {
    		bool flag = 0;
    		in[u] = 1;
    		for(int i = head[u]; i; i = e[i].nxt) {
    			int v = e[i].to;
    			if(in[v] > 1) {a[++tot] = v; s[tot] = s[tot - 1] + e[i].v; u = v; flag = 1; break;}
    		}
    		if(!flag) break;
    	}
    	if(tot == 2) {
    		int val = 0;
    		for(int i = head[S]; i; i = e[i].nxt) {
    			int v = e[i].to;
    			if(v == a[2]) val = max(val, e[i].v);
    		}
    		d[vc] = max(d[vc], f[a[1]] + f[a[2]] + val);
    		return;
    	}
    	for(int i = head[u]; i; i = e[i].nxt) {
    		int v = e[i].to;
    		if(v == S) {a[++tot] = S; s[tot] = s[tot - 1] + e[i].v; break;}
    	}
    	for(int i = tot + 1; i <= (tot - 1) * 2; ++i) {
    		a[i] = a[i - tot + 1];
    		s[i] = s[i - 1] + s[i - tot + 1] - s[i - tot]; 
    	}
    	q.clear(); q.push_back(1);
    	ll sum = 0;
    	for(int i = 2; i <= (tot - 1) * 2; ++i) {
    		while(!q.empty() && i - q.front() + 1 > (tot - 1)) q.pop_front();
    		sum = max(sum, f[a[q.front()]] + f[a[i]] + s[i] - s[q.front()]);
    		while(!q.empty() && f[a[i]] - s[i] > f[a[q.back()]] - s[q.back()]) q.pop_back();
    		q.push_back(i); 
    	}
    	d[vc] = max(d[vc], sum);
    }
    
    int main() {
    	read(n);
    	for(int x, i = 1; i <= n; ++i) {
    		ll w; read(x); read(w);
    		ins(i, x, w), ins(x, i, w);
    		in[i]++; in[x]++;
    	}
    	for(int i = 1; i <= n; ++i) {
    		if(!c[i]) bfs(i, ++Ctot); 
    	}
    	topsort();
    	for(int i = 1; i <= n; ++i) {
    		if(!vis[c[i]] && in[i] > 1) {
    			vis[c[i]] = 1;
    			dp(i, c[i]);
    			ans += d[c[i]];
    		}
    	}
    	outn(ans);
    }
    
  • 相关阅读:
    Recommended Books for Algo Trading in 2020
    Market Making is simpler than you think!
    Top Crypto Market Makers of 2020
    Top Crypto Market Makers, Rated and Reviewed
    爬取伯乐在线文章(五)itemloader
    爬取伯乐在线文章(四)将爬取结果保存到MySQL
    爬取伯乐在线文章(三)爬取所有页面的文章
    爬取伯乐在线文章(二)通过xpath提取源文件中需要的内容
    爬取伯乐在线文章(一)
    爬虫去重策略
  • 原文地址:https://www.cnblogs.com/henry-1202/p/11282209.html
Copyright © 2011-2022 走看看