2-SAT合集

hdu 1815 Building roads

2-sat问题的特征比较明显,元素的状态可以分成互相对立的两个状态并二者择其一。核心在于如何建边,剩下的套模板就可以解决,这题比较trick的一点在于
if barn1->S1,barn2->S2 then
dis(barn1,barn2 ) == dis(barn1,S1 ) + dis(barn2,S2) + dis(S1,S2)
if barn1->S1,barn2->S1 then

dis(barn1,barn2) == dis(barn1,S1) + dis(barn2,S1)

#include <cstdio>
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <cstring>
#include <queue>
#include <set>
#include <cmath>
#include <map>
#include <queue>
#include <stack>
using namespace std;
typedef long long ll;
#define urp(i,a,b) for(int i=(a),__tzg_##i=(b); i>=__tzg_##i; --i)
#define rp(i,b) for(int i=(0), __tzg_##i=(b);i<__tzg_##i;++i)
#define rep(i,a,b) for(int i=(a), __tzg_##i=(b);i<__tzg_##i;++i)
#define repd(i,a,b) for(int i=(a), __tzg_##i=(b);i<=__tzg_##i;++i)
#define mst(a,b) memset(a,b,sizeof(a))
typedef pair<int,int> pii;
#define px first
#define py second
const ll mod = 1000000007;
const double eps = 1e-6;
#define mp(a,b) make_pair(a,b)
typedef vector<int> VI;
#define px first
#define py second
const int MAXN = 505;
const int MAXM = 1005;
int N, A, B;
struct Pair {
    int x, y;
    void ipt(int k = 0) {
        scanf("%d%d", &x, &y);
        x += k;
        y += k;
    }
    Pair(int a = 0, int b = 0):x(a),y(b) {}
    int dis(const Pair & a) const {
        return abs(x-a.x) + abs(y-a.y);
    }
} S1, S2, barns[MAXN], like[MAXM], hate[MAXM], len[MAXN];
vector<int> ee1[MAXN*2], ee2[MAXN*2];
int __dis, stk[MAXN*2], top, bl[MAXN*2], cbl, vis1[MAXN*2], vis2[MAXN*2], mx_dis;
void add(int u, int v) {
    ee1[u].push_back(v);
    ee2[v].push_back(u);
}
void init() {
    rp(i, N*2) ee1[i].clear(), ee2[i].clear();
    mst(vis1, 0);
    mst(vis2, 0);
    top = 0;
    cbl = 0;
}
void setState(int dis) {
    rp(i, N) rep(j, i+1, N) {
        if (len[i].x + len[j].x > dis)
            add(i<<1, j<<1|1),
                add(j<<1, i<<1|1);
        if (len[i].x + len[j].y + __dis > dis)
            add(i<<1, j<<1),
                add(j<<1|1, i<<1|1);
        if (len[i].y + len[j].x + __dis > dis)
            add(i<<1|1, j<<1|1),
                add(j<<1, i<<1);
        if (len[i].y + len[j].y > dis)
            add(i<<1|1, j<<1),
                add(j<<1|1, i<<1);
    }
}
void dfs1(int x) {
    vis1[x] = 1;
    rp(i, ee1[x].size())
    if (!vis1[ee1[x][i]])
        dfs1(ee1[x][i]);
    stk[top++] = x;
}
void dfs2(int x) {
    vis2[x] = 1;
    bl[x] = cbl;
    rp(i, ee2[x].size())
    if (!vis2[ee2[x][i]])
        dfs2(ee2[x][i]);
}
void prepare() {
    init();
    rp(i, A) {
        add(hate[i].x*2, hate[i].y*2+1);
        add(hate[i].x*2+1, hate[i].y*2);
        add(hate[i].y*2, hate[i].x*2+1);
        add(hate[i].y*2+1, hate[i].x*2);
    }
    rp(i, B) {
        add(like[i].x*2, like[i].y*2);
        add(like[i].x*2+1, like[i].y*2+1);
        add(like[i].y*2, like[i].x*2);
        add(like[i].y*2+1, like[i].x*2+1);
    }
}
int check() {
    rp(i, 2*N) {
        if (!vis1[i])
            dfs1(i);
    }
    for(int i = top-1; i>=0; --i) {
        if (!vis2[stk[i]])
            dfs2(stk[i]), ++cbl;
    }
    rp(i, N) if (bl[i*2] == bl[i*2+1])
        return 0;
    return 1;
}
void init_main() {
    mx_dis = -1;
    rp(i, N) {
        len[i].x = barns[i].dis(S1);
        len[i].y = barns[i].dis(S2);
        mx_dis = max(mx_dis, len[i].x);
        mx_dis = max(mx_dis, len[i].y);
    }
    __dis = S1.dis(S2);
}
int solve() {
    init_main();
    prepare();
    if (!check()) {
        return -1;
    }
    int st = 0, ed = mx_dis*2+__dis;
    while (st < ed) {
        int md = (st+ed)>>1;
        prepare();
        setState(md);
        if (check())
            ed = md;
        else
            st = md+1;
    }
    return st;
}
int main() {
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
#endif
    while (scanf("%d%d%d", &N, &A, &B) != EOF) {
        S1.ipt(), S2.ipt();
        rp(i, N) barns[i].ipt();
        rp(i, A) hate[i].ipt(-1);
        rp(i, B) like[i].ipt(-1);
        printf("%d\n", solve());
    }
    return 0;
}

spoj TORNJEVI

可以说是相当恶心的一道题,一不小心居然撸了老子200+的代码。既然没人写题解,那就果断来一发吧 :-D
题意:
在一张大小为 RXS 的网格图上,n代表需要被消灭的敌人,T代表炮塔,#代表城堡。
一个炮塔发射两发炮弹,方向要求如题,炮弹沿射线运动,可消灭路径上所有的敌人和炮塔,碰到城堡则停止
求出敌人被全部消灭且炮塔无损失的前提下各个炮塔发射炮弹的方向

看着像网络流,但数据量明显略大,一个炮塔的两发炮弹方向分别只能在 (左|右)(上|下) 中二选一,有点2-sat的味道。但是每个敌人都要被消灭,这个关系的表达就不是2-sat力所能及的了。突破口在于题意明确了必定有解,且炮弹能消灭炮塔,所以对于一个n(x,y),至少存在Ta_1(x, y +|- a)或Tb_2(x +|- b,y)且T和n之间不存在#。如果|Ta|>1则Ta均不能消灭n,Tb同理。基本上就是这种类似的思路,剩下的自己意会。

#include <cstdio>
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <cstring>
#include <queue>
#include <set>
#include <cmath>
#include <map>
#include <queue>
#include <stack>
using namespace std;
typedef long long ll;
#define urp(i,a,b) for(int i=(a),__tzg_##i=(b); i>=__tzg_##i; --i)
#define rp(i,b) for(int i=(0), __tzg_##i=(b);i<__tzg_##i;++i)
#define rep(i,a,b) for(int i=(a), __tzg_##i=(b);i<__tzg_##i;++i)
#define repd(i,a,b) for(int i=(a), __tzg_##i=(b);i<=__tzg_##i;++i)
#define mst(a,b) memset(a,b,sizeof(a))
typedef pair<int,int> pii;
#define px first
#define py second
const ll mod = 1000000007;
const double eps = 1e-6;
#define mp(a,b) make_pair(a,b)
typedef vector<int> VI;
#define px first
#define py second
const int N = 105;
char mmp[N][N];
int ndx[N][N], sT, sn, r, s, nn;
const int dir[4][2] = {{-1,0}, {0,-1}, {0,1}, {1,0}};
int rdir[4][4];
vector<pii> vT, vn;
vector<VI> vr, rv, bv, blv;
VI rl, color, vis1, vis2, vtk, bl, indu;
int top, cbl;
struct Node {
    int Tdx[4];
    Node() {
        mst(Tdx, -1);
    }
};
vector<Node> Tvn;
inline int getPos(int _dx, int _dir) {
    return (_dx<<2)+_dir;
}
inline int getRev(int _dx, int _dir) {
    return (_dx<<2)+3-_dir;
}
inline int getRev(int x) {
    return (x&0xffffffc) | (3-(x&3));
}
inline void add(int u, int v) {
    vr[u].push_back(v);
    rv[v].push_back(u);
}
void cal(int _dir, int i, int role = 0) {
    pii p;
    if (!role) p = vn[i];
    else p = vT[i];
    for (int _x=p.px+dir[_dir][0], _y=p.py+dir[_dir][1], k=1;
            k&&_x>=0&&_x<r&&_y>=0&&_y<s;
            _x+=dir[_dir][0], _y+=dir[_dir][1]) {
        switch(mmp[_x][_y]) {
        case 'T':
            if (!role)
                Tvn[i].Tdx[_dir] = ndx[_x][_y];
            else
                add(getPos(i, _dir), getRev(i, _dir));
            k = 0;
            break;
        case '#':
            k = 0;
            break;
        case 'n':
            if (role)
                break;
        }
    }
}
void topo() {
    queue<int> q1, q2;
    rp(i, indu.size()) if (indu[i] == 0)
        q1.push(i);
    color.assign(cbl, 0);
    while (!q1.empty()) {
        int cur = q1.front();
        q1.pop();
        if (color[cur]) continue;
        color[cur] = 1;
        rp(i, blv[cur].size()) {
            int pos = getRev(blv[cur][i]);
            q2.push(bl[pos]);
            while (!q2.empty()) {
                pos = q2.front();
                q2.pop();
                if (color[pos]) continue;
                color[pos] = 2;
                rp(j, bv[pos].size())
                if (!color[bv[pos][j]])
                    q2.push(bv[pos][j]);
            }
        }
        rp(i, bv[cur].size()) {
            --indu[bv[cur][i]];
            if (indu[bv[cur][i]] == 0)
                q1.push(bv[cur][i]);
        }
    }
}
void dfs1(int x) {
    vis1[x] = 1;
    rp(i, vr[x].size()) {
        if (!vis1[vr[x][i]])
            dfs1(vr[x][i]);
    }
    vtk[top++] = x;
}
void dfs2(int x) {
    vis2[x] = 1;
    bl[x] = cbl;
    rp(i, rv[x].size()) {
        if (!vis2[rv[x][i]])
            dfs2(rv[x][i]);
    }
}
void init() {
    vis1.assign(rv.size(), 0);
    vis2.assign(rv.size(), 0);
    vtk.assign(rv.size(), 0);
    bl.assign(rv.size(), 0);
    top = 0;
    cbl = 0;
}
void check() {
    rp(i, vr.size()) if (!vis1[i])
        dfs1(i);
    urp(i, top-1, 0) if (!vis2[vtk[i]])
        dfs2(vtk[i]), cbl++;
    blv.assign(cbl, VI());
    rp(i, rv.size())
    blv[bl[i]].push_back(i);
    bv.assign(cbl, VI());
    indu.assign(cbl, 0);
    rp(i, rv.size()) rp(j, rv[i].size()) if (bl[i] != bl[rv[i][j]])
        bv[bl[i]].push_back(bl[rv[i][j]]),
        ++indu[bl[rv[i][j]]];
}

int main() {
#ifndef ONLINE_JUDGE
    // freopen("in.txt", "r", stdin);
#endif
    scanf("%d%d", &r, &s);
    rp(i, r) scanf("%s", mmp[i]);
    rep(i, 0, r)rep(j, 0, s) {
        switch(mmp[i][j]) {
        case 'n':
            vn.push_back(mp(i,j));
            ndx[i][j] = sn++;
            break;
        case 'T':
            vT.push_back(mp(i,j));
            ndx[i][j] = sT++;
            break;
        }
    }
    nn = sT<<1;
    vr.assign(nn<<1, VI());
    rv = vr;
    Tvn.assign(sn, Node());
    rp(i, sT) rp(j, 4) cal(j, i, 1);
    rep(i, 0, sn) {
        rep(j, 0, 4) cal(j, i);
        int da = -1, db = -1, fa, fb;
        if (Tvn[i].Tdx[0] != -1 )
            da = Tvn[i].Tdx[0], fa = 3;
        if (Tvn[i].Tdx[3] != -1 ) {
            if (da != -1)
                da = -1,
                add(getPos(Tvn[i].Tdx[0], 3), getRev(Tvn[i].Tdx[0], 3)),
                add(getPos(Tvn[i].Tdx[3], 0), getRev(Tvn[i].Tdx[3], 0));
            else
                da = Tvn[i].Tdx[3], fa = 0;
        }
        if (Tvn[i].Tdx[1] != -1 )
            db = Tvn[i].Tdx[1], fb = 2;
        if (Tvn[i].Tdx[2] != -1 ) {
            if (db != -1)
                db = -1,
                add(getPos(Tvn[i].Tdx[1], 2), getRev(Tvn[i].Tdx[1], 2)),
                add(getPos(Tvn[i].Tdx[2], 1), getRev(Tvn[i].Tdx[2], 1));
            else
                db = Tvn[i].Tdx[2], fb = 1;
        }
        if (da != -1 && db != -1)
            add(getRev(da, fa), getPos(db, fb)),
                add(getRev(db, fb), getPos(da, fa));
        else if (da != -1)
            add(getRev(da, fa), getPos(da, fa));
        else if (db != -1)
            add(getRev(db, fb), getPos(db, fb));
    }
    init();
    check();
    topo();
    rdir[1][3] = 1;
    rdir[1][0] = 4;
    rdir[2][3] = 2;
    rdir[2][0] = 3;
    rp(i, sT) {
        pii ap = vT[i];
        int dx = ndx[ap.first][ap.second];
        int _x, _y;
        int a = getPos(dx, 0);
        if (color[bl[a]] == 1)
            _x = 0;
        else
            _x = 3;
        a = getPos(dx, 1);
        if (color[bl[a]] == 1)
            _y = 1;
        else
            _y = 2;
        mmp[ap.first][ap.second] = '0' + rdir[_y][_x];
    }
    rp(i, r) puts(mmp[i]);
    return 0;
}










1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值