码迷,mamicode.com
首页 > 其他好文 > 详细

ZJU-ICPC Summer 2020 Contest 7 D Cafeterias

时间:2020-07-21 23:22:12      阅读:78      评论:0      收藏:0      [点我收藏+]

标签:math   一个   zju   struct   http   获得   直接   c++   als   

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)\)

对于询问,直接二分即可

注意,孤立节点单独判断,否则会\(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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!