IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 算法进阶-2sat-cf-1400C -> 正文阅读

[数据结构与算法]算法进阶-2sat-cf-1400C

欢迎关注更多精彩
关注我,学习常用算法与数据结构,一题多解,降维打击。

题目大意

https://codeforces.com/contest/1400/problem/C
给定长度为n的二进制串w和一个整数x,我们可以按照以下规则构造出字符串s。

1. 如 果 i > x 且 w i ? x = ′ 1 ′ , 则 s i = ′ 1 ′ 1. 如果i>x且w_{i-x}='1', 则s_i='1' 1.i>xwi?x?=1,si?=1
2. 如 果 i + x < = n 且 w i + x = ′ 1 ′ , 则 s i = ′ 1 ′ 2. 如果i+x<=n且w_{i+x}='1', 则s_i='1' 2.i+x<=nwi+x?=1,si?=1
3. 如 果 以 上 2 个 条 件 都 不 成 立 则 s i = ′ 0 ′ 3. 如果以上2个条件都不成立则s_i='0' 3.2si?=0

现在事先给出s, 问是否存在一个w可以推出s。

分析&思路

对于w[i]要么取0,要么取1,直接想到思路就是用2sat表示。

分析一下2sat建立边的过程。

  1. 对于一个坐标i如果s[i]=1 且2边x距离都有字符,那么w[i-x],w[i+x]这2个字符中至少要有1个1。
  2. 对于一个坐标i如果s[i]=0 且2边x距离都有字符,那么w[i-x],w[i+x]这2个字符都要为0。
  3. 如果一个坐标i只有1边x距离有字符,那么w[i-x] or w[i+x] = s[i]。

然后跑一遍tarjan, 求出一个可行解w。
最后要根据w恢复一下s查看是否相等。

AC代码


#include <iostream>
#include <stdio.h>
#include <queue>
#include <string.h>
#include <stack>
#include <vector>
#include <map>
#include <algorithm>
#include <assert.h>

using namespace std;


const int N = 6e5 +10;
const int E = 6e6+10;
// 边属性
class Edge {
public:
    int toVertex;
    int nextEdge;
};

// 点属性
class Node {
public:
    int head;
    int indu;
};

class Graph {
public:
    Edge edges[E];
    Node nodes[N];
    int usedEdge=0;
    Graph() {
        usedEdge = 0;
    }

    void initEdge(int n) {
        for(int i=0;i<=n;++i) {
            nodes[i].head=-1;
            nodes[i].indu  = 0;
        }
        usedEdge = 0;
    }

    void addEdge(int a, int b) {
        if(a==b) return;
        edges[usedEdge].nextEdge = nodes[a].head;
        nodes[a].head = usedEdge;
        edges[usedEdge].toVertex = b;
        nodes[b].indu++;
        usedEdge++;

        // cout<<"add edge: "<<a<<","<<b<<endl;
    }

        
    int dfn[N], low[N];
    stack<int> st;
    int deep, sum;
    int color[N];

    void initTarjan(int n) {
        deep = 0;
        sum=0;
        memset(dfn, 0,sizeof(int)*n);
        memset(low, 0,sizeof(int)*n);
        memset(color, 0,sizeof(int)*n);

    }

    void tarjan(int u) {
        dfn[u] = ++deep;
        low[u] = deep;
        st.push(u);

        for(int i=nodes[u].head;i>=0;i = edges[i].nextEdge) {
            int v = edges[i].toVertex;
            if(!dfn[v]) {
                tarjan(v);
                low[u] = min(low[u], low[v]);
            } else if(!color[v]) {
                low[u] = min(low[u], dfn[v]);
            }
        }

        if(dfn[u]==low[u]) {
            color[u] = ++sum;
            while(st.top()!=u) {
                int v = st.top();
                st.pop();
                color[v]=sum;
            }
            st.pop();
        }
    }

    map<int, int> loc;

    bool topo(int n, bool deb) {
        queue<int>qu;
        for(int i=1;i<=n;++i) {
            if(nodes[i].indu==0) {
                qu.push(i);
            }
        }
        int l=0;
        while(!qu.empty()) {
            int f = qu.front();
            loc[f]=++l;
            qu.pop();

            for(int i=nodes[f].head;i>=0;i=edges[i].nextEdge) {
                int v = edges[i].toVertex;
                nodes[v].indu--;
                if(nodes[v].indu==0) qu.push(v);
            }
        }

        if(deb) cout<<l<<endl;
        return l==n;
    }
};

Graph og;

void either(int i, bool si, int j, bool sj) {
    og.addEdge(i*2+(si^1), 2*j+sj);
    og.addEdge(j*2+(sj^1), 2*i+si);
}

void must(int i, bool sel) {
    og.addEdge(i*2+(sel^1), i*2+sel);    
}

char s[N];

void solve() {
    int x;
    scanf("%s", s);
    scanf("%d", &x);
    int n = strlen(s);
    vector<int> w(n);
    og.initEdge(2*n+10);
    // cout<<x<<endl;
    for(int i=0;i<n;++i) {
        if(i-x>=0 && i+x<n) {
            if(s[i]=='1') {
                either(i-x, 1, i+x, 1);
                continue;
            }
        }
        
        if(i-x>=0) {
            must(i-x, s[i]-'0');
        }

        if(i+x<n) {
            must(i+x, s[i]-'0');
        }
    }

    og.initTarjan(2*n +10);
    for(int i=0;i<2*n; ++i) {
        if(!og.dfn[i])og.tarjan(i);
    }

    for(int i=0;i<n;++i) {
        if(og.color[2*i] == og.color[i*2+1]){
            puts("-1");
            return;
        }
        if(og.color[2*i]<og.color[i*2+1])w[i]=0;
        else w[i]=1;
    }

    for(int i=0;i<n;++i) {
        int d=0;
        if(i-x>=0 && w[i-x]==1)d=1;
        if(i+x<n && w[i+x]==1)d=1;
        if(d!=s[i]-'0') {
            puts("-1");
            return ;
        }
    }

    for(int i=0;i<n;++i) {
        printf("%d", w[i]);
    }
    puts("");
}

int main() {
    int t;
    scanf("%d", &t);
    while(t--) {
        solve();
    }
    return 0;
}
/*

 */


本人码农,希望通过自己的分享,让大家更容易学懂计算机知识。

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-06-29 19:19:22  更:2022-06-29 19:21:47 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年4日历 -2024/4/20 18:53:17-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码