[关闭]
@xiaoziyao 2021-08-02T02:55:13.000000Z 字数 2131 阅读 747

CF641F Little Artem and 2-SAT解题报告

解题报告


CF641F Little Artem and 2-SAT解题报告:

更好的阅读体验

题意

给定两个 个点的 2-SAT 模型(各 条限制,型为 ),判断这两个模型的解集是否相同,如果不同,构造一组解使得一个有解一个无解。(

分析

憨憨题+经典题。

这道题告诉我们,2-SAT 不一定一定要用 tarjan 和 kosaraju,有时候 Floyd 也可以在 2-SAT 中有所应用。

事实上,我们用 Floyd 跑一遍传递闭包,然后再 dfs 一遍就可以解出 2-SAT 了。

首先建出来两个 2-SAT 模型,跑一遍,如果两个都无解就相似,如果一个有解一个无解就构造一组使某个模型有解。

否则有一些变量的取值是固定的,判一下是否有固定变量取值不同,或是有一个变量在一个模型确定,一个不确定,很容易构造出解。

此时两个模型的确定变量已经是相同的了,我们比较传递闭包的邻接矩阵是否相同,只要有一个不同的地方(设其为 )且 在另一个模型内均没有确定取值,就可以钦定 ,然后跑一组解就好了。

时间复杂度:

代码

2-SAT别写错,我写错了调了一个世纪 /ll 。

  1. #include<stdio.h>
  2. #include<bitset>
  3. #define rev(x) (x>n? (x-n):(x+n))
  4. using namespace std;
  5. const int maxn=1005;
  6. int n;
  7. struct two_sat{
  8. int m,ok;
  9. int fixed[maxn<<1];
  10. bitset<maxn<<1>g[maxn<<1];
  11. void get(int x){
  12. fixed[x]=1,fixed[rev(x)]=0;
  13. for(int i=1;i<=2*n;i++)
  14. if(g[x][i]&&fixed[i]==-1)
  15. get(i);
  16. }
  17. void build(){
  18. for(int i=1;i<=2*n;i++)
  19. g[i].reset(),g[i][i]=1,fixed[i]=-1;
  20. for(int i=1;i<=m;i++){
  21. int x,y;
  22. scanf("%d%d",&x,&y),x=x>0? x:rev(-x),y=y>0? y:rev(-y);
  23. g[rev(x)][y]=1,g[rev(y)][x]=1;
  24. }
  25. for(int k=1;k<=2*n;k++)
  26. for(int i=1;i<=2*n;i++)
  27. if(g[i][k])
  28. g[i]|=g[k];
  29. for(int i=1;i<=n;i++)
  30. if(g[i][n+i]&&g[n+i][i]){
  31. ok=0;
  32. return ;
  33. }
  34. ok=1;
  35. for(int i=1;i<=n;i++){
  36. if(fixed[i]==-1&&fixed[n+i]==-1&&g[i][n+i])
  37. get(n+i);
  38. if(fixed[i]==-1&&fixed[n+i]==-1&&g[n+i][i])
  39. get(i);
  40. }
  41. }
  42. void solve(){
  43. for(int i=1;i<=2*n;i++)
  44. if(fixed[i]==-1)
  45. get(i);
  46. for(int i=1;i<=n;i++)
  47. printf("%d%c",fixed[i],i==n? '\n':' ');
  48. }
  49. }A,B;
  50. int main(){
  51. scanf("%d%d%d",&n,&A.m,&B.m),A.build(),B.build();
  52. if(A.ok==0&&B.ok==0){
  53. puts("SIMILAR");
  54. return 0;
  55. }
  56. if(A.ok==0||B.ok==0){
  57. if(A.ok)
  58. A.solve();
  59. if(B.ok)
  60. B.solve();
  61. return 0;
  62. }
  63. for(int i=1;i<=2*n;i++){
  64. if(A.fixed[i]!=-1&&B.fixed[i]!=-1&&A.fixed[i]!=B.fixed[i]){
  65. A.solve();
  66. return 0;
  67. }
  68. if((A.fixed[i]==-1)+(B.fixed[i]==-1)==1){
  69. if(A.fixed[i]==-1)
  70. A.get(B.fixed[i]==0? i:rev(i)),A.solve();
  71. if(B.fixed[i]==-1)
  72. B.get(A.fixed[i]==0? i:rev(i)),B.solve();
  73. return 0;
  74. }
  75. }
  76. for(int i=1;i<=2*n;i++)
  77. for(int j=1;j<=2*n;j++){
  78. if(A.g[i][j]&&B.g[i][j]==0&&B.fixed[i]==-1&&B.fixed[i]==-1){
  79. B.get(i),B.get(rev(j)),B.solve();
  80. return 0;
  81. }
  82. if(B.g[i][j]&&A.g[i][j]==0&&A.fixed[i]==-1&&A.fixed[j]==-1){
  83. A.get(i),A.get(rev(j)),A.solve();
  84. return 0;
  85. }
  86. }
  87. puts("SIMILAR");
  88. return 0;
  89. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注