• Codeforces Round #441 (Div. 2, by Moscow Team Olympiad) E. National Property 2-SAT问题


    题目大意:

    给定N个数列,数字的范围是1-m,想通过操作使得n个数列是字典序不降的。

    操作如下:可以取某个数字x,使得n个数列里的x全部变成大写。

    数字间的大小比较是这样的: 大小比所有的小写都要小,如果大小写相同,按照数字大小比较。

    求一种可行的改变方案,使得n个数列是字典树不降的。

    题目分析:

    先考虑一维的情况,如果是n个长度是1的数列,那么如果ai  > ai + 1,那么出现矛盾,就要令ai变成大写,然后看是否出现矛盾,然后L维是同样的情况,也就是考虑有没有矛盾关系出现。

    发现每个点v的状态只有小写和大写,也就是把每个点拆成v和v',然后建边。

    如果 ai > ai + 1, 那么如果ai必定是大写,ai+1必定是小写,建边ai -> ai‘,ai + 1 -> a i +1'。

    如果ai  < ai + 1,那么如果ai + 1是大写,ai必定是大写;如果ai是小写,ai + 1必定是小写,建边ai + 1' -> ai,ai -> a i + 1。

    然后用Tarjan+Scc缩点,topsort求出一组可行解输出即可。

    (注意字典序不降,也就是如果发现 ai < ai + 1, ai > a i + 1 后就不需要向后比较了,因为更改后字典序已经大于了。

      1 #include<bits/stdc++.h>
      2 #define maxn 200010
      3 #define pb push_back
      4 using namespace std;
      5 const int MAXN = 201000;
      6 const int MAXM = 200010;
      7 struct Edge
      8 {
      9  int to,next;
     10 }edge[MAXM];
     11 int head[MAXN],tot;
     12 void init(){
     13     tot = 0;
     14     memset(head,-1,sizeof(head));
     15 }
     16 void addedge(int u,int v){
     17     edge[tot].to = v; edge[tot].next = head[u]; head[u] = tot++;
     18 }
     19 int Low[MAXN],DFN[MAXN],Stack[MAXN],Belong[MAXN];//Belong数组的值1~scc
     20 int Index,top;
     21 int scc;
     22 bool Instack[MAXN];
     23 int num[MAXN];
     24 void Tarjan(int u){
     25     int v;
     26     Low[u] = DFN[u] = ++Index;
     27     Stack[top++] = u;
     28     Instack[u] = true;
     29     for(int i = head[u]; i != -1; i = edge[i].next){
     30          v = edge[i].to;
     31          if( !DFN[v] ){
     32              Tarjan(v);
     33              if(Low[u] > Low[v])Low[u] = Low[v];
     34          }
     35         else if(Instack[v] && Low[u] > DFN[v])
     36         Low[u] = DFN[v];
     37      }
     38      if(Low[u] == DFN[u]){
     39          scc++;
     40          do{
     41              v = Stack[--top];
     42              Instack[v] = false;
     43              Belong[v] = scc;
     44              num[scc]++;
     45          }
     46          while(v != u);
     47      }
     48 }
     49 bool solvable(int n)//n是总个数,需要选择一半
     50 {
     51     memset(DFN,0,sizeof(DFN));
     52     memset(Instack,false,sizeof(Instack));
     53     memset(num,0,sizeof(num));
     54     Index = scc = top = 0;
     55     for(int i = 0;i < n;i++)
     56     if(!DFN[i])
     57          Tarjan(i);
     58      for(int i = 0;i < n;i += 2){
     59          if(Belong[i] == Belong[i^1])
     60          return false;
     61      }
     62      return true;
     63 }
     64 //*************************************************
     65 //拓扑排序求任意一组解部分
     66 queue<int>q1,q2;
     67 vector<vector<int> > dag;//缩点后的逆向DAG图
     68 char color[MAXN];//染色,为'R'是选择的
     69 int indeg[MAXN];//入度
     70 int cf[MAXN];
     71 void solve(int n){
     72     dag.assign(scc+1,vector<int>());
     73     memset(indeg,0,sizeof(indeg));
     74     memset(color,0,sizeof(color));
     75     for(int u = 0; u < n; u++)
     76     for(int i = head[u]; i != -1; i = edge[i].next){
     77          int v = edge[i].to;
     78          if(Belong[u] != Belong[v]){ 
     79              dag[Belong[v]].push_back(Belong[u]);
     80              indeg[Belong[u]]++;
     81          }
     82      }
     83      for(int i = 0; i < n; i += 2){
     84         cf[Belong[i]] = Belong[i^1];
     85         cf[Belong[i^1]] = Belong[i];
     86      }
     87     while(!q1.empty())q1.pop();
     88     while(!q2.empty())q2.pop();
     89     for(int i = 1;i <= scc;i++)
     90         if(indeg[i] == 0)
     91              q1.push(i);
     92      while(!q1.empty()){
     93          int u = q1.front();
     94          q1.pop();
     95          if(color[u] == 0){
     96              color[u] = 'R';
     97              color[cf[u]] = 'B';
     98          }
     99          int sz = dag[u].size();
    100          for(int i = 0;i < sz;i++){
    101              indeg[dag[u][i]]--;
    102              if(indeg[dag[u][i]] == 0)
    103                 q1.push(dag[u][i]);
    104         }
    105     }
    106 }
    107 bool vis[maxn];
    108 int len;
    109 vector<int> G[maxn]; 
    110 int main(){
    111      int n, m, l, x;
    112      init();
    113      cin >> n >> m;
    114      for(int i = 1; i <= n; i ++){
    115          scanf("%d",&l);
    116          len = max(len, l);
    117         for(int j = 1; j <= l; j ++){
    118             scanf("%d",&x);
    119             x --;
    120             G[i].pb(x);
    121         }
    122     }
    123     int u, v;
    124     for(int i = 2; i <= n; i ++){
    125         for(int j = 0; j < G[i].size(); j ++){    
    126             if(vis[i] || j >= G[i - 1].size()) continue;
    127             u = 2 * G[i][j], v = 2 * G[i - 1][j];
    128             if(u < v){
    129                 vis[i] = true;
    130                 addedge(v, v ^ 1);
    131                 addedge(u ^ 1, u);
    132             }
    133             else if(u > v){
    134                 vis[i] = true;
    135                 addedge(u ^ 1, v ^ 1);
    136                 addedge(v, u);
    137             } 
    138             if(j == G[i].size() - 1 && !vis[i] && G[i].size() < G[i - 1].size()){
    139                 cout << "No";
    140                 return 0;
    141             }
    142         }    
    143     }
    144     queue<int>Q;
    145      if(solvable(2*m)){
    146          solve(2*m);
    147          cout << "Yes" << endl;
    148         for(int i = 0; i < m; i ++){
    149              if(color[Belong[(2*i) ^ 1] ] == 'R') Q.push(i + 1);
    150          }
    151          cout << Q.size() << endl;
    152          while(!Q.empty()){
    153              printf("%d ",Q.front());
    154             Q.pop();    
    155         }
    156      }
    157      else{
    158          cout << "No";
    159      }
    160      return 0;
    161 }
  • 相关阅读:
    Linux 下安装 numpy 和 scipy
    排序算法总结
    机器学习&数据挖掘笔记_16(常见面试之机器学习算法思想简单梳理)
    Java读取Excel并解析文本(并格式化输出)
    快捷键记忆
    初级应该学习的
    深入理解加密、解密、数字签名和数字证书
    数据签名和验签
    POI结构与常用类
    exlipse继承反编译插件
  • 原文地址:https://www.cnblogs.com/poler/p/7681547.html
Copyright © 2020-2023  润新知