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
一开始同以为是找重心,然后各种不会做……
后来看题解发现思路很神奇……
因为一单位时间每人只能传给一个人,所以这个人周围的节点是依次接到信息的
于是可以给它周围的节点分配一个边权
子树越大的节点越要先传递,边权就越小
所以枚举一遍从哪个点开始向四周传信息
最后统计最小值以及方案就可以了
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<vector> using namespace std; const int N=1009; int cnt,p[N],n,ans=int(1e9),an[N],f[N]; bool vis[N]; struct edge{ int to,nex; }e[N<<1]; vector<int>q[N]; bool cmp(int x,int y){return x>y;} void add(int u,int v) { ++cnt; e[cnt]=(edge){v,p[u]}; p[u]=cnt; } void dfs(int u) { for(int i=p[u];i;i=e[i].nex) { int v=e[i].to; if(vis[v])continue; vis[v]=1; dfs(v); q[u].push_back(f[v]); } sort(q[u].begin(),q[u].end(),cmp); for(int i=1;i<=q[u].size();++i) f[u]=max(f[u],q[u][i-1]+i); } int main() { scanf("%d",&n); for(int i=2;i<=n;++i) { int x; scanf("%d",&x); add(x,i);add(i,x); } for(int i=1;i<=n;++i) { memset(f,0,sizeof(f)); memset(vis,0,sizeof(vis)); for(int j=1;j<=n;++j)q[j].clear(); vis[i]=1; dfs(i); an[i]=f[i]; ans=min(an[i],ans); } cout<<ans+1<<endl; for(int i=1;i<=n;++i) if(an[i]==ans)cout<<i<<" "; return 0; }
by:wypx
s:新机房太棒了
w:突然换机房……幸福来的好突然