2018.8.11T1(贪心,基环树)

编程入门 行业动态 更新时间:2024-10-07 04:33:20

2018.8.11T1(<a href=https://www.elefans.com/category/jswz/34/1769875.html style=贪心,基环树)"/>

2018.8.11T1(贪心,基环树)

描述
有 n 座城市,其中编号为 1 的是首都。

城市之间只能通过单向的传送器进行移动。每座城市有且仅有一个传送器,第 i 个城市的传送器指向城市 ai。保证从任意城市出发,经过若干次传送,都能到达首都。

小A喜欢 K 这个数,他想让你修改一些城市的传送器,使得从每个城市出发,走恰好 K 步后都能恰好停在首都。

求最少需要修改多少个城市的传送器。

输入格式
第一行两个数 n, K。

第二行 n 个数 a1~an,表示每个城市初始的传送器指向的城市编号。

输出格式
一行一个数,表示最少需要修改多少个城市的传送器。

样例1
样例输入1
3 1
2 3 1
样例输出1
2
样例2
样例输入2
8 2
5 4 2 1 1 7 2 4
样例输出2
3


仔细观察你会发现,题目绕来绕去,就是给了你一个树形结构
不过这是一个奇环内向树
实际上是单个环
当然如果你足够优秀,你会直接发现1必须连自己,然后你随便给每个节点重新定父亲,问最少需要给几个节点重新定父亲
实际上我们只要贪心的做就行了
很多人的做法是从上往下搜,把 k+1,2k+1,3k+1 k + 1 , 2 k + 1 , 3 k + 1 层全部改掉
实际上这样是错的,不是最优的
要从下往上搜
为什么?
实际上抽象的想,从上往下相当于把从上往下选择的层向上移若干层。
那移动之后的点数肯定比移动前的点数要少。
故从下往上搜肯定比从上往下搜更优

#include<bits/stdc++.h>
using namespace std;
#define rep(i,j,k) for(int i = j;i <= k;++i)
#define repp(i,j,k) for(int i = j;i >= k;--i)
#define ll long long
int n , k;
int a[100100] , fa[100100] , hash[100100];
struct deep{int num , id;
}dep[100100];
vector<int>G[100100];
bool flag[100100];
int read()
{int sum = 0;char c = getchar();bool flag = true;while( c < '0' || c > '9' ) {if(c == '-') flag = false;c = getchar();}while( c >= '0' && c <= '9' ) sum = sum * 10 + c - 48 , c = getchar();if(flag)  return sum;else return -sum;
}  
queue<int>q;
void print1()
{int now = 0;rep(i,1,n) if(a[i] != 1) now++;printf("%d\n",now);exit(0);
}
void change(int x)
{fa[x] = 1;q.push(x);dep[hash[x]].num = 1;while(q.size()){int x = q.front();flag[x] = true;rep(i,1,G[x].size()){if(flag[G[x][i-1]]) continue;dep[hash[G[x][i-1]]].num = dep[hash[x]].num + 1;q.push(G[x][i-1]);}q.pop();}return;
}
bool mycmp(deep a,deep b)
{return a.num > b.num;
}
int solve1()
{int sum = 0;sort(dep + 1,dep + n + 1,mycmp);rep(i,1,n) hash[dep[i].id] = i; rep(i,1,n)if(dep[i].num <= k) continue;else{int now = dep[i].id;rep(i,1,k-1) now = fa[now];change(now);sum++;}if(a[1] != 1) sum++;return sum;
}
void init()
{n = read();k = read();rep(i,1,n) {a[i] = read();if(i == 1) continue;G[a[i]].push_back(i);fa[i] = a[i];}if(k == 1) print1();q.push(1);while(q.size()){int x = q.front();rep(i,1,(G[x].size())){dep[G[x][i-1]].num = dep[x].num +1;q.push(G[x][i-1]);}q.pop();}rep(i,1,n) dep[i].id = i;printf("%d\n",solve1());return;
}
int main()
{init();return 0;
} 

更多推荐

2018.8.11T1(贪心,基环树)

本文发布于:2024-02-25 17:37:56,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1699783.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:贪心   基环树

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!