Codeforces 876E National Property ——(2-SAT)

  在这题上不是标准的“a或b”这样的语句,因此需要进行一些转化来进行建边。同时在这题上点数较多,用lrj大白书上的做法会T,因此采用求强连通分量的方法来求解(对一个点,如果其拓扑序大于其为真的那个点,则这个语句为真,都相同则无解,否则为假)。AC代码如下:

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 const int N = 1e5 + 5;
  4 typedef long long ll;
  5 
  6 int n,m,dfs_clock,dfn[N*2],low[N*2];
  7 int belong[N*2],scc_cnt;
  8 stack<int> S;
  9 vector<int> G[N*2];
 10 
 11 void init()
 12 {
 13     for(int i=1;i<=n;i++) G[i].clear();
 14     dfs_clock = 0;
 15     memset(dfn,0,sizeof(dfn));
 16     memset(belong,0,sizeof(belong));
 17     scc_cnt = 0;
 18 }
 19 
 20 void tarjan(int u)
 21 {
 22     dfn[u]=low[u]=++dfs_clock;
 23     S.push(u);
 24     for(int i=0;i<G[u].size();i++)
 25     {
 26         int v = G[u][i];
 27         if(!dfn[v])
 28         {
 29             tarjan(v);
 30             low[u]=min(low[u],low[v]);
 31         }
 32         else if(!belong[v])
 33         {
 34             low[u]=min(low[u],dfn[v]);
 35         }
 36     }
 37     if(low[u]==dfn[u])
 38     {
 39         scc_cnt++;
 40         for(;;)
 41         {
 42             int x = S.top();S.pop();
 43             belong[x] = scc_cnt;
 44             if(x==u) break;
 45         }
 46     }
 47 }
 48 
 49 void add(int x, int y) {G[x].push_back(y);}
 50 
 51 void solve()
 52 {
 53     for(int i=0;i<2*m;i++)
 54     {
 55         if(!dfn[i]) tarjan(i);
 56     }
 57     vector<int> ans;
 58 
 59     for(int i=0;i<2*m;i+=2)
 60     {
 61         if(belong[i] == belong[i+1])
 62         {
 63             puts("No");
 64             return ;
 65         }
 66         else
 67         {
 68             if(belong[i] > belong[i+1]) ans.push_back(i/2+1);
 69         }
 70     }
 71     puts("Yes");
 72     printf("%d
",ans.size());
 73     for(int i=0;i<ans.size();i++) printf("%d%c",ans[i],i==ans.size()-1?'
':' ');
 74 }
 75 
 76 vector<int> v[N];
 77 
 78 int main()
 79 {
 80     cin >> n >> m;
 81     for(int i=1;i<=n;i++)
 82     {
 83         int t; scanf("%d",&t);
 84         while(t--)
 85         {
 86             int x; scanf("%d",&x);
 87             v[i].push_back(x);
 88         }
 89     }
 90     init();
 91     for(int i=1;i<n;i++)
 92     {
 93         int sz = min(v[i].size(), v[i+1].size());
 94         int pos = -1;
 95         for(int j=0;j<sz;j++)
 96         {
 97             if(v[i][j] != v[i+1][j])
 98             {
 99                 pos = j;
100                 break;
101             }
102         }
103         if(pos == -1)
104         {
105             if(v[i].size() <= v[i+1].size()) continue;
106             else return 0*puts("No");
107         }
108         int x = v[i][pos]-1;
109         int y = v[i+1][pos]-1;
110         if(x < y)
111         {
112             add(y<<1|1, x<<1|1);
113             add(x<<1, y<<1);
114         }
115         else
116         {
117             add(x<<1, x<<1|1);
118             add(y<<1|1, y<<1);
119         }
120     }
121     solve();
122     return 0;
123 }
原文地址:https://www.cnblogs.com/zzyDS/p/7771630.html