• 2020提高组模拟赛7 StormWind


    StormWind

    中文 切换语言(Change Language)

    时间:4s   空间:512M

    题目描述:

    风暴城建造的防线错综复杂,可以抽象成一个有$n$个点$m$条边的有向拓扑图,暴风城的最长防线定义为以任意一个点开始能走的最长路径的边数。

    由于部落的进攻有所侧重,所以安度因每天会临时下一些命令来调整防线。

    第一种 $ty = 1$ $x$点不能被经过。

    第二种 $ty = 2$ 必须经过$x$点。

    第三种 $ty = 3$ 必须经过输入顺序的第$x$条边。

    每一天的调整不会影响到下一天。

    求每一天下完命令之后的最长防线。

    输入格式:

    第一行三个数$n$,$m$,$k$. 分别表示点数、边数、天数。

    以后$m$行每行数$x$,表示$x ->y$ 有一条边。以后k行每行两个数$ty,x$;

    输出格式:

    对于每个询问 输出一行表示其结果

    样例输入:

    6  5  3

    1  2

    1  3

    1  4

    1  5

    2  3

    1  2

    3  1

    2  5

    样例输出:

    1

    2

    1

    数据范围:

    对于$20\%$的数据 

    $n,m,k<=5000$

    另有$20\%$的数据

    保证 对于 $1<=i<n$, $i$ 与 $i + 1$ 之间有边。

    另有$10\%$的数据 没有操作$1$、$2$

    对于$100\%$的数据

    $n,m,k<=2e5$ 

    拓扑排序

    首先先加一个超级源点和超级汇点,可以发现最长路径一定会从超级源点出发,或者结束于超级汇点

    首先考虑第二个和第三个操作,要处理出来从源点出发到这个点的最长路$ds[i]$,和从这个点到汇点的最长路$dt[i]$,这个可以通过拓扑序DP更新

    对于第二个操作,那么要强制经过这个点,那么答案就是$ds[i]+dt[i]$

    对于第三个操作,那么要强制经过边两端的端点,那么答案就是$ds[u]+dt[v]+1$

    主要是难以对第一个操作进行处理,考虑钦定某一个点不能经过,最长路径的贡献来自三个部分,这个点“左边”(拓扑序小于这个点的拓扑序)的点,可以贡献从源点到这些点最长的路径;在这个点“右边”(拓扑序大于这个点的拓扑序)的点,可以贡献从这点到汇点最长的路径;还有就是“左边”连到“右边” 的点,贡献就是$ds[i]+dt[j]+1$

    考虑如何计算对于每一个点的贡献

    从左边推到右边,枚举到第i个点时,要去除$ds[i]$的贡献和连向这个点的边的贡献,就是$ds[j]+1+dt[i]$(存在$j->i$的边),然后加上$dt[i]$的贡献

    这个可以用set来维护

    #include <bits/stdc++.h>
    using namespace std;
    const int N=2*1e5+100;
    int n,m,k,ds[N],dt[N],s,t,dg[N];
    int dout[N],din[N],vi[N],a[N],w;
    int ans[N],premax[N],sucmax[N],id[N];
    queue <int> q;
    multiset <int> S;
    multiset <int> :: iterator it;
    struct node
    {
        int u,v;
    }sh[N];
    vector <int> e[N],E[N],p;
    void get()
    {
        for (int i=1;i<=n;i++)
        {
            for (int j=0;j<(int)E[i].size();j++)
              dg[E[i][j]]++;
        }
        for (int i=1;i<=n;i++)
        {
            if (dg[i]==0)
            {
                q.push(i);
                vi[i]=1;
            }
        }
        while (!q.empty())
        {
            int x=q.front();
            q.pop();
            a[++w]=x;
            for (int i=0;i<(int)E[x].size();i++)
            {
                int u=E[x][i];
                if (vi[u]) continue;
                dg[u]--;
                if (dg[u]==0) q.push(u),vi[u]=1;
            }
        }
        dt[t]=0;
        for (int i=1;i<=n;i++)
        {
            int x=a[i];
            for (int j=0;j<(int)E[x].size();j++)
            {
                int u=E[x][j];
                dt[u]=max(dt[u],dt[x]+1);
            }
        }
        memset(dg,0,sizeof(dg));
        memset(vi,0,sizeof(vi));
        for (int i=1;i<=n;i++)
        {
            for (int j=0;j<(int)e[i].size();j++)
              dg[e[i][j]]++;
        }
        for (int i=1;i<=n;i++)
        {
            if (dg[i]==0)
            {
                q.push(i);
                vi[i]=1;
            }
        }
        w=0;
        while (!q.empty())
        {
            int x=q.front();
            q.pop();
            a[++w]=x;
            for (int i=0;i<(int)e[x].size();i++)
            {
                int u=e[x][i];
                if (vi[u]) continue;
                dg[u]--;
                if (dg[u]==0) q.push(u),vi[u]=1;
            }
        }
        ds[s]=0;
        for (int i=1;i<=n;i++)
        {
            int x=a[i];
            for (int j=0;j<(int)e[x].size();j++)
            {
                int u=e[x][j];
                ds[u]=max(ds[u],ds[x]+1);
            }
        }
        for (int i=1;i<=n;i++) id[a[i]]=i;
        for (int i=1;i<=n;i++) premax[i]=max(premax[i],ds[a[i]]);
        for (int i=n;i>=1;i--) sucmax[i]=max(sucmax[i+1],dt[a[i]]);
    }
    inline void del(int x)
    {
        it=S.lower_bound(x);
        S.erase(it);
    }
    int main()
    {
        scanf("%d%d%d",&n,&m,&k);
        for (int i=1;i<=m;i++)
        {
            scanf("%d%d",&sh[i].u,&sh[i].v);
            dout[sh[i].u]++;din[sh[i].v]++;
            e[sh[i].u].push_back(sh[i].v);
            E[sh[i].v].push_back(sh[i].u);
        }
        s=n+1;t=n+2;
        for (int i=1;i<=n;i++)
        {
            if (din[i]==0) e[s].push_back(i),E[i].push_back(s);
            if (dout[i]==0) e[i].push_back(t),E[t].push_back(i);
        }
        n+=2;
        get();
        for (int i=1;i<=n;i++)
        {
            for (int j=0;j<(int)E[a[i]].size();j++)
            {
                int u=E[a[i]][j];
                del(ds[u]+dt[a[i]]+1);
            }
            if (!S.empty())it=S.end(),it--,ans[a[i]]=(*it)-2;
            ans[a[i]]=max(ans[a[i]],premax[i-1]-1);
            ans[a[i]]=max(ans[a[i]],sucmax[i+1]-1);
            for (int j=0;j<(int)e[a[i]].size();j++)
            {
                int u=e[a[i]][j];
                S.insert(ds[a[i]]+dt[u]+1);
            }
        }
        while (k--)
        {
            int ty,x;
            scanf("%d%d",&ty,&x);
            if (ty==1) printf("%d
    ",ans[x]);
            if (ty==2) printf("%d
    ",ds[x]+dt[x]-2);
            if (ty==3) printf("%d
    ",ds[sh[x].u]+dt[sh[x].v]-1);
        }
    }
    View Code
  • 相关阅读:
    立项管理--复习需加强知识点
    Python函数中的->none是什么意思和作用
    信息系统项目管理基础--复习需加强知识点
    python笔记
    案例分析--课堂笔记
    对下载的软件包做校验
    pc端和公众号同时开发的方案选择
    应用服务器拖垮数据库问题排查
    常用的idea插件
    如何进行后端开发 (大体逻辑)
  • 原文地址:https://www.cnblogs.com/huangchenyan/p/13509228.html
Copyright © 2020-2023  润新知