luogu P2018 消息传递
Posted ck666
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luogu P2018 消息传递相关的知识,希望对你有一定的参考价值。
P2018 消息传递
2017-09-13
题目描述
巴蜀国的社会等级森严,除了国王之外,每个人均有且只有一个直接上级,当然国王没有上级。如果A是B的上级,B是C的上级,那么A就是C的上级。绝对不会出现这样的关系:A是B的上级,B也是A的上级。
最开始的时刻是0,你要做的就是用1单位的时间把一个消息告诉某一个人,让他们自行散布消息。在任意一个时间单位中,任何一个已经接到消息的人,都可以把消息告诉他的一个直接上级或者直接下属。
现在,你想知道:
1.到底需要多长时间,消息才能传遍整个巴蜀国的所有人?
2.要使消息在传递过程中消耗的时间最短,可供选择的人有那些?
输入输出格式
输入格式:
输入文件的第一行为一个整数N(N≤1000),表示巴蜀国人的总数,假如人按照1到n编上了号码,国王的编号是1。第2行到第N行(共N-1行),每一行一个整数,第i行的整数表示编号为i的人直接上级的编号。
输出格式:
文件输出共计两行:
第一行为一个整数,表示最后一个人接到消息的最早时间。
第二行有若干个数,表示可供选择人的编号,按照编号从小到大的顺序输出,中间用空格分开。
输入输出样例
输入样例#1:
8 1 1 3 4 4 4 3
输出样例#1:
View Code
5 3 4 5 6 7
原本一看这个题,暴力找重心,然后跑树,然后经过仔细读题,发现并没有用到重心,我们只要找到一个点到树的最长的一条带边权的路径和最大的最小。
f每一个点上的边权是从1到所连边个数的全排列,(因为每一次只能传一个)所以我们贪心选取使边权的大值对应它所连点底下边权和较小的值.
每一层强行sort加权.ans统计最小
#include<iostream> #include<cstdio> #include<cstdlib> #include<algorithm> #include<vector> #include<cstring> #define ll long long #define _ =read(); using namespace std; const int maxn=1000+100; int read(){ int an=0,f=1; char ch=getchar(); while(!(‘0‘<=ch&&ch<=‘9‘)){if(ch==‘-‘);ch=getchar();} while(‘0‘<=ch&&ch<=‘9‘){an=an*10+ch-‘0‘;ch=getchar();} return an*f; } vector<int>b[maxn]; bool vis[maxn]; int wi[maxn],n; int f[maxn],ans[maxn],mi=(int)1e9; bool saber(int x,int y){ return wi[x]>wi[y]; } void dfs(int x){ vis[x]=1; for(int i=0;i<b[x].size();i++){ if(!vis[ b[x][i] ]){ dfs(b[x][i]); } } sort(b[x].begin(),b[x].end(),saber); for(int i=0;i<b[x].size();i++){ wi[x]=max(i+1+wi[b[x][i]],wi[x]); } vis[x]=0; } int main(){ n _ for(int i=2;i<=n;i++){ int x=read(); b[i].push_back(x); b[x].push_back(i);} for(int i=1;i<=n;i++){ dfs(i); ans[i]=wi[i]; mi=min(mi,ans[i]); memset(wi,0,sizeof(wi)); } cout<<mi<<endl; for(int i=1;i<=n;i++)if(ans[i]==mi)cout<<i<<" "; return 0; }
by:s_a_b_e_r
以上是关于luogu P2018 消息传递的主要内容,如果未能解决你的问题,请参考以下文章