病毒传递
Description
小毒物想要让微生物世界里的所有细菌都感染上病毒。
微生物世界的等级观念很强,除了菌王外,每个细菌均有且只有一个直接的母体,菌王则没有母体。
如果细菌a是细菌b的母体,细菌b是细菌c的母体,则细菌a就是细菌c的母体。绝不会出现这样两个细菌a、b:细菌a是细菌b的母体,细菌b是细菌a的母体。
最开始的时刻为0,小毒物要做的就是用1个单位时间把病毒传递给某一个“病毒源细菌”,然后让细菌们自行传递。在任意一个单位时间中,任何一个已经被感染的细菌,都可以将病毒传递给它的一个直接母体或直接的下一个细菌。
现在,小毒物想知道的是:
1.最少需要多长时间,所有的细菌都会感染上病毒;
2.使感染时间最短时,可供选择的“病毒源细菌”有哪些。
Input
第一行一个数N。表示全部的细菌数。并且从1到N编上号,毒王为1。
第二行到第N行(共N-1行),每行一个数。第I行的数表示细菌I的直接母体的编号。
Output
第一行一个数。表示最后一个细菌被感染后的最早时间。
第二行若干个数。表示可供选择的“病毒源细菌”的编号。
Sample Input
81 1 1 2 2 3 7
Sample Output
51 2 3
Answer
/**
感觉这个题写的很垃圾
暴力每个点作为起点的时间,取最小值
设dp[i]为遍历完i的子树需要的时间
如果j是i的子树
那么肯定是先遍历dp[j]大的子树(这样传染过j点之后j能有更多的时间往下传)
so……………………
然而人家让输出时间我傻逼的输出了多少个方案居然也对了两个测试点…………………………
**/
#include
#define maxn (1000 + 10)
#define inf (1 << 30) - 1
using namespace std;
vector V[maxn];
int dp[maxn];
bool vis[maxn];
void dfs(int p) {
if(vis[p] == true) return;
if(V[p].size() == 1 && vis[V[p][0]] == true) {
dp[p] = 0;
return ;
}
if(dp[p] != 0) return ;
vis[p] = true;
int temp[maxn];
int l = 0;
for(int i = 0; i < V[p].size(); i ++) {
int q = V[p][i];
if(vis[q] == false) {
dfs(q);
temp[l ++] = dp[q];
}
}
sort(temp,temp + l);
for(int i = 0; i < l; i ++) {
dp[p] = max(dp[p],temp[i] + l - i);
}
vis[p] = false;
}
int re[maxn];
int main() {
// freopen("in.txt","r",stdin);
int n,mins = inf,cnt = 0;
scanf("%d",&n);
for(int i = 2; i <= n; i ++) {
int pre;
scanf("%d",&pre);
V[pre].push_back(i);
V[i].push_back(pre);
}
for(int i = 1; i <= n; i ++) {
memset(dp,0,sizeof(dp));
memset(vis,false,sizeof(vis));
dfs(i);
re[i] = dp[i];
mins = min(mins,re[i]);
}
for(int i = 1; i <= n; i ++) {
if(re[i] == mins) cnt ++;
}
printf("%d\n",mins + 1);
for(int i = 1; i <= n; i ++) {
if(re[i] == mins) printf("%d ",i);
}
printf("\n");
return 0;
}