AGC004_D Teleporter
阿新 • • 發佈:2018-12-19
題面大意:
有n個城市,每個城市有一個傳送點,都可以傳送到唯一的另外一個城市,保證從任何位置出發經過若干次傳送之後能夠到達1號城市。現在希望修改一些點的目的地,使得從任何一點出發在傳送K次之後恰好都能到達1號城市,求最少要改變目的地的城市的數量。
Translated by @加藤聖教_封仙
思路:
首先一號點必須連向自己,因為存在兩個點,一個點到1號點的最短路徑等於另一個點的路徑+1,而你每次只能經過環來增加自己的路徑長度,然而只存在一個環,所以此環長度必為1。之後我們就只要讓所有點到1號點的最短路徑小於等於k即可。我們可以貪心的想,每次將深度最深的點往上走k-1步的點連向1號點即可,然後那個點的子樹就均滿足條件了。空間O(n),時間O(n)。
#include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<vector> using namespace std; const int maxn=1e5; int n,k,ans,tot; vector<int>vr[maxn+8]; int pre[maxn+8],now[maxn+8],son[maxn+8],dep[maxn+8],fa[maxn+8]; bool vis[maxn+8]; int read() { int x=0,f=1;char ch=getchar(); for (;ch<'0'||ch>'9';ch=getchar()) if (ch=='-') f=-1; for (;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; return x*f; } void add(int u,int v) { pre[++tot]=now[u]; now[u]=tot; son[tot]=v; } void dfs(int x) { vr[dep[x]].push_back(x); for (int p=now[x];p;p=pre[p]) { int child=son[p]; fa[child]=x;dep[child]=dep[x]+1; dfs(child); } } void solve(int x) { for (int i=1;i<=k;i++) { if (vis[x]) return; vis[x]=1; x=fa[x]; } ans+=(x!=1); } int main() { n=read(),k=read(); int x=read();if (x!=1) ans=1; for (int i=2;i<=n;i++) { int f=read(); add(f,i); } dfs(1); vis[1]=1; for (int i=n;i;i--) for (vector<int>::iterator it=vr[i].begin();it!=vr[i].end();it++) solve(*it); printf("%d\n",ans); return 0; }