#6175. 「美团 CodeM 初赛 Round B」黑白树

xiaoxiao2021-02-28  56

题意就丢个链接吧:https://loj.ac/problem/6175

看完题之后,我的第一反应就是跑拓扑图啊

因为我比较无脑,然后就开始打了

WA了。。。。

然后想啊想啊,最后喵了眼题解,发现了一句重要的情况

假设有这样一种情况:

其K:4 10 2 2 1 1 1 1

这样的话,我们肯定先选8作为起点,染色到5.那么暴力去想的话继续以4为起点,染色到4,再以3为起点,染色到3..............依次类推的话,其结果就是5.

但是显然我们的正解答案是2.

这样就很尴尬啊,于是我重新想。。。

(⊙v⊙)嗯

感觉问题不大啊,我依然跑拓扑图,然后在跑之前dfs一次树,把k值更新一下就好了嘛

感觉很对啊

最后要加上一点点优化,就是类似于并查集的路径压缩,这样可以省去许多跳的时间

于是这题就可以A了

#include<cstdio> #include<algorithm> #include<iostream> #include<cstring> #include<queue> using namespace std; const int N=100005; struct qq{int x,y,last;}e[N]; int num,last[N]; int n; int k[N]; int mymax (int x,int y){return x>y?x:y;} int mymin (int x,int y){return x<y?x:y;} void init (int x,int y) { num++; e[num].x=x;e[num].y=y; e[num].last=last[x]; last[x]=num; } int dep[N]; void dfs (int x) { for (int u=last[x];u!=-1;u=e[u].last) { int y=e[u].y; dep[y]=dep[x]+1; dfs(y); } } void lalal1 (int x)//更新k值 { for (int u=last[x];u!=-1;u=e[u].last) { int y=e[u].y; lalal1(y); k[x]=mymin(k[x],k[y]); } } int fa[N]; int ru[N]; queue<int> q; bool lalal[N]; int f[N]; int find (int x) { if (lalal[x]==false) return x; f[x]=find(f[x]); return f[x]; } void solve () { int ans=0; for (int u=1;u<=n;u++) if (ru[u]==0) q.push(u); while (!q.empty()) { int x=q.front();q.pop(); ru[fa[x]]--;if (fa[x]!=0&&ru[fa[x]]==0) q.push(fa[x]); if (lalal[x]==true) continue; ans++; int xx=x; do { lalal[x]=true; x=find(x); }while (dep[x]>=k[xx]); } printf("%d\n",ans); } int main() { memset(lalal,false,sizeof(lalal)); memset(ru,0,sizeof(ru)); num=0;memset(last,-1,sizeof(last)); scanf("%d",&n); for (int u=2;u<=n;u++) { int x; scanf("%d",&x); init(x,u); f[u]=x; fa[u]=x;ru[x]++; } dep[1]=1;dfs(1); for (int u=1;u<=n;u++) { int x; scanf("%d",&x); k[u]=mymax(1,dep[u]-x+1); } lalal1(1); solve(); return 0; }

转载请注明原文地址: https://www.6miu.com/read-59284.html

最新回复(0)