zoukankan      html  css  js  c++  java
  • 题解 P4381 【[IOI2008]Island】

    题目链接

    为什么我感觉所有树上简单问题到了基环树上都成了毒瘤……

    Solution [IOI2008]Island

    题目大意:给定基环树森林,求每棵树的直径之和

    动态规划-树形dp,单调队列,基环树


    分析:

    首先如果把"基环"去掉就是sb题

    我们用(f[u])表示以(u)为根的子树的最长链,假定有边(e)

    (f[u]=max{f[e.to]+e.dist})

    (ans[u])表示以(u)为根的子树的直径

    (ans[u]=max{ans[e.to],f'[u] + f[e.to]+e.dist})

    一棵树直径有两种可能,它子树的直径和过它根的直径,由子树(ans)转移不解释,(f')代表更新前的(f),我们用之前子树的最长链加上当前子树的最长链得到第二种情况

    树形(dp)可以(O(n))解决

    然后在基环树上,直径分两种,不经过环的直径和经过环的直径

    不经过环的直径我们在环上点的(ans)中找个(max)即可

    如果我们要求经过环的直径,假定(u,v)均在环上,显然(ans=max{f[u]+f[v]+dis(u,v)}),其中(dis(u,v))为环上两点两条路径中较长的那条

    这玩意儿如果暴力是(O(n^3))的,加上前缀和可以做到(O(n^2))

    由于同时考虑两个方向不好做,我们断环成链

    (ans=max{f[u]+f[v]+sum[u]-sum[v] quad v<u}),我们把环上距离做个前缀和得到(sum),然后这个东西就可以用单调队列来优化到(O(n))

    窝学艺不精导致的玄学(bug:)

    (0)小于一个负数

    问题:使用了(vector)所致,(vector.size())返回值(size\_t),该类型为无符号整数,然后有符号数和无符号数运算会统一成无符号数运算……无符号数存负数就会(GG)

    (Trick:)题目保证每个点出度为(1),如果我们建反图就是一棵外向树

    #include <cstdio>
    #include <cctype>
    #include <vector>
    #include <algorithm>
    #include <queue>
    using namespace std;
    const int maxn = 1e6 + 100;
    typedef long long ll;
    inline int read(){
    	int x = 0;char c = getchar();
    	while(!isdigit(c))c = getchar();
    	while(isdigit(c))x = x * 10 + c - '0',c = getchar();
    	return x;
    }
    struct Edge{int to,dist;};
    vector<Edge> G[maxn],rG[maxn];
    vector<int> cir[maxn];
    int deg[maxn],vis[maxn],iscir[maxn],q[maxn << 1],head,tail,n,cir_tot;
    ll f[maxn],ans[maxn],sum[maxn << 1],val[maxn << 1],ansout;
    inline void dfs(int u){
    	for(auto e : G[u]){
    		if(iscir[e.to])continue;
    		dfs(e.to);
    		ans[u] = max(ans[u],f[u] + f[e.to] + e.dist);
    		ans[u] = max(ans[u],ans[e.to]);
    		f[u] = max(f[u],f[e.to] + e.dist);
    	}
    }
    inline void topo(){
    	queue<int> Q;
    	for(int i = 1;i <= n;i++){
    		iscir[i] = 1;	
    		if(!deg[i])Q.push(i);
    	}
    	while(!Q.empty()){
    		int u = Q.front();Q.pop();
    		iscir[u] = 0;
    		for(auto e : rG[u])
    			if(!--deg[e.to])Q.push(e.to);
    	}
    	for(int i = 1;i <= n;i++)
    		if(iscir[i] && !vis[i]){
    			int now = i;cir_tot++;
    			do{
    				for(auto e : G[now])
    					if(iscir[e.to]){
    						cir[cir_tot].push_back(e.to);
    						vis[now = e.to] = 1;break;
    					}
    			}while(now != i);
    		}
    }
    inline void solve(){
    	for(int id = 1;id <= cir_tot;id++){
    		reverse(cir[id].begin(),cir[id].end());
    		ll tmp = 0;
    		for(int x : cir[id])
    			dfs(x),tmp = max(tmp,ans[x]);
    		for(int i = 0;i < cir[id].size();i++){
    			int u = cir[id][i],pre = i == 0 ? cir[id][cir[id].size() - 1] : cir[id][i - 1];
    			for(auto e : G[u])
    				if(e.to == pre){sum[i] = sum[i + cir[id].size()] = e.dist;break;}
    		}
    		for(int i = 1;i < cir[id].size() * 2;i++)
    			sum[i] += sum[i - 1];
    		for(int i = 0;i < cir[id].size() * 2;i++)
    			val[i] = f[cir[id][i % cir[id].size()]] - sum[i];
    		q[head = tail = 1] = 0;
    		for(int i = 1;i < cir[id].size() * 2;i++){
    			while(head <= tail && q[head] <= (i - (int)cir[id].size()))head++;
    			if(head <= tail)tmp = max(tmp,f[cir[id][i % cir[id].size()]] + sum[i] + val[q[head]]);
    			while(head <= tail && val[q[tail]] <= val[i])tail--;
    			q[++tail] = i;
    		}
    		ansout += tmp;
    	}
    }
    inline void addedge(int from,int to,int dist){
    	G[from].push_back(Edge{to,dist});
    	deg[from]++;
    	rG[to].push_back(Edge{from,0}); 
    }
    int main(){
    	n = read();
    	for(int u,v = 1;v <= n;v++)
    		u = read(),deg[u]++,G[u].push_back(Edge{v,read()}),rG[v].push_back(Edge{u,0});
    	topo();
    	solve();
    	printf("%lld
    ",ansout);
    	return 0;
    }
    
  • 相关阅读:
    Word常用定义的变量
    Delphi对Word一些进阶操作
    Delphi 统计Word文档中的字数
    Delphi对Word的基本操作
    Spring3 MVC请求参数获取的几种方法
    Spring3系列13-Controller和@RequestMapping
    Spring3系列12-Spring AOP AspectJ
    Spring3系列11-Spring AOP——自动创建Proxy
    Spring3系列10-Spring AOP——Pointcut,Advisor拦截指定方法
    Spring3系列9-Spring AOP——Advice
  • 原文地址:https://www.cnblogs.com/colazcy/p/11818362.html
Copyright © 2011-2022 走看看