标签:math 一个 zju struct http 获得 直接 c++ als
https://zjusummer.contest.codeforces.com/group/clkkguw3vK/contest/102661/problem/D
对于一个节点,设有食物时为黑色,无食物时为白色,可以发现,一个节点顶多经历三个阶段
这样比较难处理,我们对于奇偶分别讨论
一个状态记录为\((v,eo)\),\(v\)表示其节点标号,\(eo\)表示其奇偶性,那么对于一个状态,只有前面全白,后面全黑的过渡过程
我们记录每个状态第一次黑色的位置,可以通过最短路获得,直接\(BFS\)
转移:\((u,eo)->(v,eo \quad xor\quad 1)\)
对于询问,直接二分即可
注意,孤立节点单独判断,否则会\(WA\)
\(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);
}
}
}
ZJU-ICPC Summer 2020 Contest 7 D Cafeterias
标签:math 一个 zju struct http 获得 直接 c++ als
原文地址:https://www.cnblogs.com/GK0328/p/13357035.html