ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

NWRRC2015 Insider’s Information

2021-09-28 21:36:29  阅读:161  来源: 互联网

标签:Information PutLeft Cur NWRRC2015 else Insider Le Prs Vis


NWRRC2015 Insider’s Information

题意

对于 \([1, n]\) 的排列,给 \(m\) 个限制,第 \(i\) 个限制描述 \(b_i\) 出现在 \(a_i\),\(c_i\) 之间。保证存在一个排列满足所有限制。

构造一个 \(n\) 的排列至少满足 \(\lceil \frac m2 \rceil\) 个限制。

分析

每个限制连接两条有向边 \((a_i,b_i)\),\((c_i,b_i)\),因为所有限制都可以被满足,所以在原序列中的端点一定入度为 \(0\)。

这个图虽然存在环,但是我们对这个图进行拓扑排序,一次删除一个约束的两条边,仍然是可以将所有点入队出队的,但是排序后仅能保证其中每个约束中,\(b\) 点不会同时排在 \(a\),\(c\) 前面。但是这已经足够做此题了。

证明很简单,如果一个 \(b\) 的度变成 \(0\),一定是它的所有入边都被删除了,所以不存在 \(b\) 被删除,\(a\),\(c\) 都仍未删除的情况。

我们按拓扑序考虑将点加入最左边还是最右边,从两边往中间堆元素,直到填满排列为止。

对于一个约束,第一个放入的如果是 \(b\),则无论 \(a\),\(b\) 怎么放,都不可能满足约束,而我们的拓扑排序不存在 \(b\) 第一个放的情况。

如果第一个放的是 \(a\) 或 \(c\),第二个放的点的位置就决定了该约束是否能满足。

如果第二个放的是 \(b\),那么它放在第一个放的元素同侧,则最后一个元素无论怎么放,约束都满足。如果放在异侧,则无论最后一个元素怎么放,约束都不满足。

如果第二个放的是 \(a\) 或 \(c\) 那么第三个放的一定是 \(b\),所以第一个和第二个放的 \(a\),\(c\) 只要在异侧,约束一定满足,在同侧则一定不满足。

我们对于每个枚举的元素,统计它属于的约束中,有多少次是第二个放的元素,然后统计这些情况中,是放在左端满足的约束多还是放在右端满足的约束多,放到满足约束多的一侧,这样就保证了一定满足 \(\lceil \frac m2 \rceil\) 个限制。

代码实现

因为每个约束会给 \(b_i\) 带来两个入度,而拓扑排序时我们需要给 \(b_i\) 减去两个入度,所以为了方便,不如直接用一个入度表示一个约束。

过程中我们一遍拓扑排序一边处理,因为每个点的位置只和已经放入排列中的点有关,所以这样处理也是正确的。

实现还是很短的,指针轻喷。

unsigned m, n, M;
unsigned Top(0), Tl(0), Hd(0);
unsigned A, B, C, D, t;
unsigned Cnt(0), Ans[100005], Tmp(0), BdL(0), BdR;
struct Que;
struct Node {
  vector<Que*> Bel; 
  unsigned Deg;
  char Vis, Le;
}N[100005], * Queue[100005];
struct Que {
  Node* Le, * Ri, * Mid;
  Que* Nxt;
}Q[100005];
signed main() {
  BdR = (n = RD()) + 1, m = RD();
  for (unsigned i(1); i <= m; ++i) {
    A = RD(), B = RD(), C = RD(), ++N[B].Deg;
    Q[i].Le = N + A, N[A].Bel.emplace_back(Q + i);
    Q[i].Mid = N + B, N[B].Bel.emplace_back(Q + i);
    Q[i].Ri = N + C, N[C].Bel.emplace_back(Q + i);
  }
  for (unsigned i(1); i <= n; ++i) if(!N[i].Deg) Queue[++Tl] = N + i;
  while (Tl ^ Hd) {//Topo and Solve 
    Node* Cur(Queue[++Hd]);
    unsigned PutLeft(100000);
    Cur->Vis = 1;
    for (auto Prs:Cur->Bel) {
      if(Cur == Prs->Le) {//Cur is A
        if(Prs->Ri->Vis) {//2nd or 3rd
          if(!(Prs->Mid->Vis)) {if(Prs->Ri->Le) --PutLeft; else ++PutLeft;}//2nd Add
        } else if(!(--(Prs->Mid->Deg))) Queue[++Tl] = Prs->Mid;//1st Add
      } else {//Cur is C or B
        if(Cur == Prs->Ri) {//Cur is C
          if(Prs->Le->Vis) {//2nd or 3rd
            if(!(Prs->Mid->Vis)) {if(Prs->Le->Le) --PutLeft; else ++PutLeft;}//2nd Add
          } else if(!(--(Prs->Mid->Deg)))Queue[++Tl] = Prs->Mid; //1st Add
        } else {//Cur is B
          if(!((Prs->Ri->Vis) & (Prs->Le->Vis))) {//2nd Add
            if(Prs->Ri->Vis) {if(Prs->Ri->Le) ++PutLeft;else --PutLeft;}//1st is C
            else {if(Prs->Le->Le) ++PutLeft;else --PutLeft;}//1st is A
          }
        }
      }
    }
    Cur->Le = (PutLeft >= 100000);
    Ans[(PutLeft < 100000) ? (--BdR) : (++BdL)] = Cur - N; 
  }
  for (unsigned i(1); i <= n; ++i) printf("%u ", Ans[i]);
  return Wild_Donkey;
}

标签:Information,PutLeft,Cur,NWRRC2015,else,Insider,Le,Prs,Vis
来源: https://www.cnblogs.com/Wild-Donkey/p/15350120.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有