LightOJ 1251 Forming the Council(2-set入门)

2-set

  • 定义: 有n个布尔变量\(x_i\)和m个形如\(x_i = true/false || x_j = true /false\)的条件,问能否为每个变量赋值使得,m个条件均被满足
  • 解决: 对每个变量\(x_i\),拆成\(2i和2i+1\)两个点分别表示\(x_i\)为\(false/true\),最后对每个变量都设置一个赋值.

对于\(x_i = true || x_j = false\),在\(2i和2j\)建有向边(\(x_i\)为假,则\(x_j\)一定为假),在\(2j+1和2i+1\)建有向边(\(x_j\)为真则\(x_i\)一定为真)

求解时,我们考虑当前没有被赋值的变量\(x_i\),他只能为真/假,先假定他为假,在遍历后序所有的节点,如果能够全部赋值,则求解成功. 否则回退到当前\(x_i\),并令其为真,在进行一次遍历,若依然不成功,则问题无解

LightOj 1251

  • 题意: 2-set裸题
  • 思路: 对于 +1 +3 我们建如下两条边,其他情况同理
#include<bits/stdc++.h>
#define lson(p) (p<<1)
#define rson(p) (p<<1|1)
#define ll long long
using namespace std;
const int N = 1e5+10;

struct edge{
    int to,nxt;
}e[N*10];
int head[N],tot;
void init(){
    tot = 0;
    memset(head,0,sizeof head);
}
void add(int u,int v){
    e[++tot].to = v; e[tot].nxt = head[u]; head[u]=tot;
}
bool vis[N];
int S[N],top;

bool dfs(int u){
    if(vis[u^1])    return false;
    if(vis[u])  return true;
    vis[u] = true;
    S[top++] = u;
    for(int i=head[u];i;i=e[i].nxt){
        if(!dfs(e[i].to))   return false;
    }
    return true;
}

bool Twosat(int n){
    memset(vis,0,sizeof vis);
    for(int i=0;i<n;i+=2){
        if(vis[i] || vis[i^1])  continue;
        top = 0;
        if(!dfs(i)){
            while(top) vis[S[--top]] = false;
            if(!dfs(i+1))  return false;
        }
    }
    return true;
}
vector<int> ans;
int main(){
    int n,m;
    int u,v;
    char op1,op2;
    int t;
    scanf("%d",&t);
    for(int _=1;_<=t;++_){
        init();
        ans.clear();
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;++i){
            scanf(" %c%d %c%d",&op1,&u,&op2,&v);
            u--; v--;
            u *= 2 ;    v*=2;
            if(op1=='+')    u++;
            if(op2=='+')    v++;
// printf("%d %d %d %d\n",u,v^1,v,u^1);
            add(v^1,u); add(u^1,v);
        }
        printf("Case %d: ",_);
        if(Twosat(m*2)){
            printf("Yes\n");
            for(int i=0;i<m;i++){
                if(vis[i*2+1]){
                    ans.push_back(i);
                }
            }
            printf("%d",ans.size());
            for(auto i:ans){
                printf(" %d",i+1);
            }puts("");
        }else{
            printf("No\n");
        }
    }
}

原文地址:https://www.cnblogs.com/xxrlz/p/11399127.html

时间: 2024-10-16 01:21:32

LightOJ 1251 Forming the Council(2-set入门)的相关文章

Light OJ 1251 Forming the Council 2-SAT输出任意一组解

题目来源:Light OJ 1251 Forming the Council 题意:若干了条件至少满足一个 求是否有方案 输出任意一种可能的方案 留下的人的个数 思路:2-SAT基础题 #include <cstdio> #include <cstring> #include <vector> using namespace std; const int maxn = 100010; int n, m; vector <int> G[maxn*2]; boo

Light oj 1251 - Forming the Council 【2-sat】【推断是否存在可行解 + 反向拓扑输出可行解】

1251 - Forming the Council problem=1251" style="color:rgb(79,107,114)"> PDF (English) problem=1251" style="color:rgb(79,107,114)">Statistics problem=1251" style="color:rgb(79,107,114)">Forum Time Limit

Light oj 1251 - Forming the Council 【2-sat】【判断是否存在可行解 + 反向拓扑输出可行解】

1251 - Forming the Council PDF (English) Statistics Forum Time Limit: 2 second(s) Memory Limit: 32 MB In a city there are n voters, and m people formed the Govt. council. The council members are numbered from 1 to m. Now everyone is complaining that

HDU 1251 统计难题(字典树入门模板题 很重要)

统计难题 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131070/65535 K (Java/Others)Total Submission(s): 56382    Accepted Submission(s): 19709 Problem Description Ignatius最近遇到一个难题,老师交给他很多单词(只有小写字母组成,不会有重复的单词出现),现在老师要他统计出以某个字符串为前缀的单词数量(单词本身也是自己的

HDU 1251 裸的字典树、入门题

裸的字典树还是挺简单的. 四个基本操作建立.查找.插入.删除 建立新结点我是用的c++中 new操作.当然也可以用malloc,都方便 不过指针阿.地址阿.这其中关系什么的我貌似还不是很清楚阿. 因为刚开始我的头结点也是定义的指针.然后程序就炸了.我不清楚原因呢. 有待弄清楚. 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #includ

LightOJ 1236 Pairs Forming LCM (LCM 唯一分解定理 + 素数筛选)

http://lightoj.com/volume_showproblem.php?problem=1236 Pairs Forming LCM Time Limit:2000MS     Memory Limit:32768KB     64bit IO Format:%lld & %llu Submit Status Practice LightOJ 1236 Description Find the result of the following code: long long pairs

HDU 1251 字典树入门

统计难题 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131070/65535 K (Java/Others)Total Submission(s): 17177    Accepted Submission(s): 7410 Problem Description Ignatius最近遇到一个难题,老师交给他很多单词(只有小写字母组成,不会有重复的单词出现),现在老师要他统计出以某个字符串为前缀的单词数量(单词本身也是自己的前

hdu 1251 统计难题 (字典树入门题)

1 /******************************************************* 2 题目: 统计难题 (hdu 1251) 3 链接: http://acm.hdu.edu.cn/showproblem.php?pid=1251 4 算法: 字典树 5 提示: 这题压要用c++提交,G++会超内存 6 *******************************************************/ 7 #include<cstdio> 8

LightOJ 1236 - Pairs Forming LCM (LCM&#183;唯一分解)

题意  给你一个数n  求满足lcm(a, b) == n, a <= b 的 (a,b) 的个数 容易知道 n 是a, b的所有素因子取在a, b中较大指数的积 先将n分解为素数指数积的形式  n = π(pi^ei)    那么对于每个素因子pi  pi在a,b中的指数ai, bi 至少有一个等于pi, 另一个小于等于pi 先不考虑a, b的大小  对于每个素因子pi 1. 在a中的指数 ai == ei   那么 pi 在 b 中的指数可取 [0, ei] 中的所有数  有 ei + 1