zoukankan      html  css  js  c++  java
  • 洛谷 P2018 消息传递 题解

    题面

    总体来说是一道从下往上的DP+贪心;

    设f[i]表示将消息传给i,i的子树全部接收到所能消耗的最小时间;

    那么对于i的所有亲儿子节点j,我们会贪心地先给f[j]大的人传递,然后次大.....

    可以证明,这样的答案一定是最优的;

    然后f[i]=max(f[i],f[j]+cnt);

    总的时间复杂度是O(n^2logn),可过;

    但是还可以进一步优化(窝太懒了所以没写)

    换根法,可以一遍dfs(nlogn)就求出所有的答案;

    #include <bits/stdc++.h>
    #define inc(i,a,b) for(register int i=a;i<=b;i++)
    using namespace std;
    int head[2010],cnt;
    class littlestar{
    	public:
    	int to,nxt;
    	void add(int u,int v){
    		to=v; nxt=head[u];
    		head[u]=cnt;
    	}
    }star[4010];
    int n;
    int f[2010];
    class node{
    	public:
    	int value,pos;
    };
    vector<node> vec[2010];
    bool cmp(node x,node y)
    {
    	return x.value>y.value;
    }
    void dfs(int u,int fa)
    {
    	for(int i=head[u];i;i=star[i].nxt){
    		int v=star[i].to;
    		if(v==fa) continue;
    		dfs(v,u);
    		vec[u].push_back((node){f[v],v});	
    	}
    	sort(vec[u].begin(),vec[u].end(),cmp);
    	inc(j,0,(int)vec[u].size()-1){
    		int v=vec[u][j].pos;
    		f[u]=max(f[u],f[v]+j+1);
    	}
    }
    int tmp[2010];
    int main()
    {
    	scanf("%d",&n);
    	inc(i,2,n){
    		int tmp; scanf("%d",&tmp);
    		star[++cnt].add(tmp,i);
    		star[++cnt].add(i,tmp);
    	}
    	int minn=INT_MAX;
    	inc(i,1,n){
    		memset(f,0,sizeof(f));
    		inc(j,1,n) vec[j].clear();
    		dfs(i,0);
    		if(f[i]<minn){
    			tmp[0]=0;
    			tmp[++tmp[0]]=i;
    			minn=f[i];
    		}
    		else if(f[i]==minn){
    			tmp[++tmp[0]]=i;
    		}
    	}
    	printf("%d
    ",minn+1);
    	inc(i,1,tmp[0]){
    		printf("%d ",tmp[i]);
    	}
    }
    /*
    8
    1
    1
    3
    4
    4
    4
    3
    */
    
  • 相关阅读:
    Java自学二十六天
    Java自学三十四天
    Java自学三十二天
    Java自学三十天
    Java开学考试心得
    Java自学二十九天
    Java自学二十八天
    Java自学三十一天
    Java自学三十三天
    2020年月12日Java学习日记
  • 原文地址:https://www.cnblogs.com/kamimxr/p/11808330.html
Copyright © 2011-2022 走看看