zoukankan      html  css  js  c++  java
  • bzoj 2535 & bzoj 2109 航空管制 —— 贪心+拓扑序

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2535

    https://www.lydsy.com/JudgeOnline/problem.php?id=2109

    这个题,如果正着考虑,也就是先考虑放在前面的再考虑放在后面的,决策时会有矛盾;
    也就是,如果要求 pos[a] < pos[b],则先考虑放 a,因为许多点放在 a 后面,所以 a 尽量往前放可以给它们留出空位;
    但又有限制最晚起飞时间,那么先考虑的 a 应该尽量放在靠近它最晚起飞时间的地方,以免后面的点无法满足起飞时间的限制;
    于是尽量往前放和尽量往后放形成了矛盾,无法决策;
    所以需要转化一个限制,不妨对于 pos[a] < pos[b],先决策 b;
    于是两个限制合起来的要求就都变成尽量往后放了(真神奇);
    所以我们就这样倒着做,一定能得到合法的序列;
    然后考虑每个点的可能最前位置,其实就是做的过程中把这个点以及它限制的点都暂时去掉,让其他点放好,那么不能再放的时候就意味着只有放上这个点才能继续,这时这个点按刚才做法找到的位置就是它的最前位置(其他点已经尽量把它的可行位置挤到前面了);
    注意放点位置是最晚起飞时间和限制它的点的起飞时间取 min 的!
    注意答案是起飞序列!而不是每个点的起飞位置!
    如果用 set 找某位置前面第一个空位会很慢,还是并查集好。
    代码如下:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<set>
    using namespace std;
    int const xn=2005,xm=10005;
    int n,m,hd[xn],ct,to[xm],nxt[xm],deg[xn],tmp[xn],ans[xn],d[xn],mn[xn];
    struct N{
      int v,id;
      N(int v=0,int i=0):v(v),id(i) {}
    };
    queue<int>q;
    set<int>st;
    set<int>::iterator it;
    int rd()
    {
      int ret=0,f=1; char ch=getchar();
      while(ch<'0'||ch>'9'){if(ch=='-')f=0; ch=getchar();}
      while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar();
      return f?ret:-ret;
    }
    void add(int x,int y){to[++ct]=y; nxt[ct]=hd[x]; hd[x]=ct;}
    void topo(int nw)
    {
      for(int i=1;i<=n;i++)
        {
          mn[i]=min(n,d[i]); tmp[i]=deg[i];
          if(!tmp[i]&&i!=nw)q.push(i);
        }
      while(q.size())
        {
          int x=q.front(); q.pop();
          it=st.lower_bound(n-mn[x]+1);
          int tim=*it;
          //ans[x]=n-tim+1; //!!!
          ans[n-tim+1]=x;
          st.erase(tim);
          for(int i=hd[x],u;i;i=nxt[i])
        {
          if((u=to[i])==nw)continue;
          tmp[u]--; mn[u]=min(mn[u],mn[x]);//!!
          if(!tmp[u])q.push(u);
        }
        }
    }
    int solve(int x)
    {
      st.clear();
      for(int i=1;i<=n;i++)st.insert(i);
      topo(x);
      it=st.lower_bound(n-d[x]+1);
      return n-*it+1;
    }
    int main()
    {
      n=rd(); m=rd();
      for(int i=1;i<=n;i++)d[i]=rd(),st.insert(i);
      for(int i=1,x,y;i<=m;i++)x=rd(),y=rd(),add(y,x),deg[x]++;
      topo(0);
      for(int i=1;i<=n;i++)printf("%d ",ans[i]); puts("");
      for(int i=1;i<=n;i++)printf("%d ",solve(i)); puts("");
      return 0;
    }
    set
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    using namespace std;
    int const xn=2005,xm=10005;
    int n,m,hd[xn],ct,to[xm],nxt[xm],deg[xn],tmp[xn],ans[xn],d[xn],mn[xn];
    int fa[xn],q[xn];
    int rd()
    {
      int ret=0,f=1; char ch=getchar();
      while(ch<'0'||ch>'9'){if(ch=='-')f=0; ch=getchar();}
      while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar();
      return f?ret:-ret;
    }
    void add(int x,int y){to[++ct]=y; nxt[ct]=hd[x]; hd[x]=ct;}
    int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
    void topo(int nw)
    {
      int cnt=0;
      for(int i=1;i<=n;i++)
        {
          mn[i]=min(n,d[i]); tmp[i]=deg[i]; fa[i]=i;
          if(!tmp[i]&&i!=nw)q[++cnt]=i;
        }
      while(cnt)
        {
          int x=q[cnt--]; int tim=find(mn[x]);
          ans[tim]=x; fa[tim]=tim-1;
          for(int i=hd[x],u;i;i=nxt[i])
        {
          if((u=to[i])==nw)continue;
          tmp[u]--; mn[u]=min(mn[u],mn[x]);//!!
          if(!tmp[u])q[++cnt]=u;
        }
        }
    }
    int solve(int x)
    {
      topo(x); return find(d[x]);
    }
    int main()
    {
      n=rd(); m=rd();
      for(int i=1;i<=n;i++)d[i]=rd();
      for(int i=1,x,y;i<=m;i++)x=rd(),y=rd(),add(y,x),deg[x]++;
      topo(0);
      for(int i=1;i<=n;i++)printf("%d ",ans[i]); puts("");
      for(int i=1;i<=n;i++)printf("%d ",solve(i)); puts("");
      return 0;
    }
  • 相关阅读:
    ABP框架理论研究总结(典藏版)
    ABP系列文章总目录:
    使用NServiceBus开发分布式应用
    shell脚本进阶 详解及其实例(一)
    linux模拟实现主机跨路由通信
    网络管理之基础知识详解
    RAID RAID 大揭秘~
    磁盘管理(一)磁盘结构
    如何在centos7上安装源码包
    压缩与解压缩
  • 原文地址:https://www.cnblogs.com/Zinn/p/10134492.html
Copyright © 2011-2022 走看看