[AGC004D] Teleporter [贪心]
题面:
思路:
分析可知,这道题中的图是一个环套内向树,首都在环上
首先有一个结论:当首都的出边指向首都时,一定最优(不然首都出发可能无法按时到达首都)(可以按时到达的情况也一定有到不了的)
这种情况下首都构成自环,其他边构成一棵指向首都的树
因此可以这样贪心地解决问题:
从所有的叶节点开始拓扑排序,记录每一个节点下属的深度最大的叶节点的深度
如果有一个节点的距离(上述深度)到达了k-1,那么就把这个节点拆下来接到首都上面,剩下的节点继续作为新叶节点拓扑排序
这样所有1的子树的深度都在k以内,到达首都以后可以走自环达到k
Code:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 inline int read(){ 7 int re=0,flag=1;char ch=getchar(); 8 while(ch>'9'||ch<'0'){ 9 if(ch=='-') flag=-1; 10 ch=getchar(); 11 } 12 while(ch>='0'&&ch<='9') re=(re<<1)+(re<<3)+ch-'0',ch=getchar(); 13 return re*flag; 14 } 15 int n,K,a[100010],dep[100010]; 16 int q[100010],head=0,tail=0,cnt[100010]; 17 int main(){ 18 int i,u,ans=0; 19 n=read();K=read(); 20 a[1]=read(); 21 if(a[1]!=1) ans++,a[1]=1; 22 for(i=2;i<=n;i++) a[i]=read(),cnt[a[i]]++; 23 // for(i=1;i<=n;i++) cout<<cnt[i]<<ends;cout<<endl; 24 for(i=1;i<=n;i++) if(!cnt[i]) q[tail++]=i; 25 while(head<tail){ 26 u=q[head++]; 27 // cout<<"topo "<<u<<ends<<dep[u]<<endl; 28 if(u==1) break; 29 if(a[u]!=1&&dep[u]==K-1) ans++; 30 else dep[a[u]]=max(dep[a[u]],dep[u]+1); 31 cnt[a[u]]--; 32 if(cnt[a[u]]==0) q[tail++]=a[u]; 33 } 34 printf("%d\n",ans); 35 }