ZJU-ICPC Summer 2020 Contest 7 D Cafeterias
阿新 • • 發佈:2020-07-21
https://zjusummer.contest.codeforces.com/group/clkkguw3vK/contest/102661/problem/D
對於一個節點,設有食物時為黑色,無食物時為白色,可以發現,一個節點頂多經歷三個階段
\(1.\)一直是白色
\(2.\)黑白閃爍
\(3.\)一直是黑色
這樣比較難處理,我們對於奇偶分別討論
一個狀態記錄為\((v,eo)\),\(v\)表示其節點標號,\(eo\)表示其奇偶性,那麼對於一個狀態,只有前面全白,後面全黑的過渡過程
我們記錄每個狀態第一次黑色的位置,可以通過最短路獲得,直接\(BFS\)
轉移:\((u,eo)->(v,eo \quad xor\quad 1)\)
對於詢問,直接二分即可
\(C++ Code:\)
#include<iostream> #include<cstdio> #include<algorithm> #include<queue> #define N 4000005 using namespace std; int n,m,k,x,y,t,T; int tot,head[N],nxt[N],d[N],rd[N]; int c[N],g[2][N],g0[N],g1[N]; bool s[N]; struct node { int dis,eo,id; }; queue<node>q; void add(int x,int y) { tot++; d[tot]=y; nxt[tot]=head[x]; head[x]=tot; rd[y]++; } void Solve() { for (int i=1;i<=n;i++) g[0][i]=-1,g[1][i]=-1; for (int i=1;i<=k;i++) if (s[c[i]]) q.push((node){1,1,c[i]}),g[1][c[i]]=0; while (!q.empty()) { node u=q.front(); q.pop(); for (int i=head[u.id];i;i=nxt[i]) { int v=d[i]; if (g[u.eo^1][v]!=-1) continue; q.push((node){u.dis+1,u.eo^1,v}); g[u.eo^1][v]=u.dis+1; } } } int main() { scanf("%d%d%d",&n,&m,&k); for (int i=1;i<=k;i++) { scanf("%d",&c[i]); s[c[i]]=true; } for (int i=1;i<=m;i++) { scanf("%d%d",&x,&y); add(x,y); add(y,x); } for (int i=1;i<=n;i++) if (!rd[i]) s[i]=false; Solve(); for (int i=1;i<=n;i++) g0[i]=g[0][i],g1[i]=g[1][i]; sort(g0+1,g0+n+1); int g_0=0; for (int i=1;i<=n;i++) if (g0[i]==-1) g_0++; sort(g1+1,g1+n+1); int g_1=0; for (int i=1;i<=n;i++) if (g1[i]==-1) g_1++; scanf("%d",&T); while (T --> 0) { scanf("%d",&t); if (t==1) printf("%d\n",k); else { int o; if (t&1) o=upper_bound(g1+1,g1+n+1,t)-g1-1; else o=upper_bound(g0+1,g0+n+1,t)-g0-1; o=min(o,n); o-=(t&1)?g_1:g_0; printf("%d\n",o); } } }