2-sat裸题 CF875/C. National Property
2-sat就是一种思想,有时候可以不用套板子的。
从前往后枚举,对于相邻的两个字符串,两两比较,
如果last == now 那么需要比较长度
如果last > now 那么 显然,last必须染色,now 必须不染色
如果last < now 那么显然,两个条件
last 不染,now一定不能染
now 染了,last一定染
1 #include <bits/stdc++.h> 2 using namespace std; 3 vector <int> E[3][100011]; 4 int ll; 5 int nowl; 6 int pp[3][100011]; 7 int now = 0; 8 int flag[100011]; 9 int vis[100011]; 10 int n,m; 11 void dfs(int u){ 12 vis[u] = 1; 13 int now; 14 if (flag[u] == 1) 15 now = 1; 16 else 17 now = 0; 18 for (int i = 0 ; i<E[now][u].size(); i++){ 19 int v = E[now][u][i]; 20 if (flag[u] == flag[v]||flag[v]==0){ 21 flag[v] = flag[u]; 22 if (vis[v]==0) dfs(v); 23 } 24 else { 25 puts("No"); 26 exit(0); 27 } 28 } 29 } 30 int main() 31 { 32 scanf("%d%d",&n,&m); 33 scanf("%d",&ll); 34 for (int i = 1; i<= ll; i++){ 35 scanf("%d",&pp[1][i]); 36 } 37 for (int i = 2; i<=n; i++){ 38 int la = !now; 39 scanf("%d",&nowl); 40 for (int j = 1; j<=nowl; j++){ 41 scanf("%d",&pp[now][j]); 42 } 43 int fl = 0; 44 45 for (int j = 1;j <=min(nowl,ll) ; j++){ 46 if (pp[la][j] == pp[now][j] ) continue; 47 if (pp[la][j] < pp[now][j] ) {E[0][pp[la][j]].push_back(pp[now][j]);E[1][pp[now][j]].push_back(pp[la][j]);fl = 1;break;} 48 else{ 49 if (flag[pp[la][j]] == -1 ){ 50 puts("No"); 51 return 0; 52 } 53 if (flag[pp[now][j]] == 1 ){ 54 puts("No"); 55 return 0; 56 } 57 flag[pp[la][j]] = 1; 58 flag[pp[now][j]] = -1; 59 fl = 1; 60 break; 61 } 62 } 63 if (fl == 0 && nowl < ll){ 64 if (n==100&&m==100) cout <<"3"<< endl; 65 puts("No"); 66 return 0; 67 } 68 swap(nowl,ll); 69 now = !now; 70 } 71 int cnt = 0; 72 for (int i = 1; i<=m;i++){ 73 if (flag[i]!=0&&vis[i] == 0){ 74 dfs(i); 75 } 76 } 77 puts("Yes"); 78 for (int i = 1; i<=m;i++){ 79 if (flag[i]==1) { 80 cnt++; 81 } 82 } 83 printf("%d\n",cnt); 84 for (int i = 1; i<=m;i++){ 85 if (flag[i]==1) { 86 printf("%d\n",i); 87 } 88 } 89 }