当前位置: 首页 > news >正文

2-SAT 题目整理

其实就是把kb菊苣整理的题目刷了一遍。


poj-3648 Wedding

细节:不让新娘看到有奸情的任意一对同时在对面一侧,则必选新郎,然后构造新郎那侧的可行解,然后将染相反颜色的人输出(要求输出新娘那侧的人)。

代码1(任意可行解):

#include <algorithm>
#include <iostream>
#include <string.h>
#include <vector>
#include <cstdio>
#include <queue> 
using namespace std;
const int maxn = 65;
const int maxm = maxn*maxn;
struct node {int u, v, next;} edge[maxm];
int no, head[maxn];
int dfn[maxn], low[maxn], index, sta[maxn], top;
bool vis[maxn];
int bel[maxn], cnt;
vector<int> g[maxn];
queue<int> q;
int opp[maxn], deg[maxn], col[maxn];
int n, m;
void init()
{
	no = 0;
	memset(head, -1, sizeof head);
	index = 0, top = 0;
	memset(dfn, 0, sizeof dfn);
	memset(vis, 0, sizeof vis);
	cnt = 0;
	memset(deg, 0, sizeof deg);
	memset(col, 0, sizeof col);
}
inline void add(int u, int v)
{
	edge[no].u = u; edge[no].v = v;
	edge[no].next = head[u]; head[u] = no++;
}
void tarjan(int u)
{
	dfn[u] = low[u] = ++index;
	sta[++top] = u, vis[u] = 1;
	for(int k = head[u]; k+1; k = edge[k].next)
	{
		int v = edge[k].v;
		if(!dfn[v])
		{
			tarjan(v);
			low[u] = min(low[u], low[v]);
		}
		else if(vis[v]) low[u] = min(low[u], dfn[v]);
	}
	if(dfn[u] == low[u])
	{
		++cnt;
		do
		{
			vis[sta[top]] = 0;
			bel[sta[top]] = cnt;
			--top;
		}
		while(sta[top+1] != u);
	}
}
void print()
{
	for(int i = 1; i < n; ++i)
	{
		if(i > 1) printf(" ");
		if(col[bel[i*2]] != 1) printf("%dh", i);
		if(col[bel[i*2+1]] != 1) printf("%dw", i);
	}
	printf("\n");
}
void topsort()
{
	for(int i = 1; i <= cnt; ++i) g[i].clear();
	for(int i = 0; i < no; ++i)
	{
		int u = edge[i].u, v = edge[i].v;
		if(bel[u] == bel[v]) continue;
		g[bel[v]].push_back(bel[u]);
		++deg[bel[u]];
	}
	while(!q.empty()) q.pop();
	for(int i = 1; i <= cnt; ++i)
	if(!deg[i]) q.push(i);
	while(!q.empty())
	{
		int u = q.front(); q.pop();
		if(!col[u])
		col[u] = 1, col[opp[u]] = -1;
		for(int i = 0; i < g[u].size(); ++i)
		{
			int v = g[u][i];
			if(--deg[v] == 0) q.push(v);
		}
	}
}
void work()
{
	for(int i = 0; i < n*2; ++i)
	if(!dfn[i]) tarjan(i);
	for(int i = 0; i < n; ++i)
	{
		if(bel[i*2] == bel[i*2+1])
		{
			puts("bad luck");
			return;
		}
		else
		{
			opp[bel[i*2]] = bel[i*2+1];
			opp[bel[i*2+1]] = bel[i*2];
		} 
	}
	topsort();
	print();
}
void mapping()
{
	for(int i = 1; i <= m; ++i)
	{
		int u, v;
		char c1, c2;
		scanf("%d%c %d%c", &u, &c1, &v, &c2);
		u *= 2, v *= 2;
		if(c1 == 'w') ++u;
		if(c2 == 'w') ++v;
		add(u, (v^1));
		add(v, (u^1));
	}
	add(1, 0);
}
int main()
{
	while(~scanf("%d %d", &n, &m) && n+m)
	{
		init();
		mapping();
		work();
	}
	return 0;
}

代码2(字典序最小的解):

#include <algorithm>
#include <iostream>
#include <string.h>
#include <vector>
#include <cstdio>
#include <queue> 
using namespace std;
const int maxn = 65;
const int maxm = maxn*maxn;
struct node {int u, v, next;} edge[maxm];
int no, head[maxn];
int col[maxn], sta[maxn], top;
int n, m;
void init()
{
	no = 0;
	memset(head, -1, sizeof head);
	memset(col, 0, sizeof col);
}
inline void add(int u, int v)
{
	edge[no].u = u; edge[no].v = v;
	edge[no].next = head[u]; head[u] = no++;
}
void print()
{
	for(int i = 1; i < n; ++i)
	{
		if(i > 1) printf(" ");
		if(col[i*2] != 1) printf("%dh", i);
		if(col[i*2+1] != 1) printf("%dw", i);
	}
	printf("\n");
}
bool dfs(int u)
{
	if(col[u^1]) return 0;
	if(col[u]) return 1;
	col[u] = 1;
	sta[++top] = u;
	for(int k = head[u]; k+1; k = edge[k].next)
	{
		int v = edge[k].v;
		if(!dfs(v)) return 0;
	}
	return 1;
}
void work()
{
	for(int i = 0; i < n; ++i)
	{
		if(col[i*2] || col[i*2+1]) continue;
		top = 0;
		if(!dfs(i*2))
		{
			while(top) col[sta[top--]] = 0;
			if(!dfs(i*2+1))
			{
				puts("bad luck");
				return;
			}
		}
	}
	print();
}
void mapping()
{
	for(int i = 1; i <= m; ++i)
	{
		int u, v;
		char c1, c2;
		scanf("%d%c %d%c", &u, &c1, &v, &c2);
		u *= 2, v *= 2;
		if(c1 == 'w') ++u;
		if(c2 == 'w') ++v;
		add(u, (v^1));
		add(v, (u^1));
	}
	add(1, 0);
}
int main()
{
	while(~scanf("%d %d", &n, &m) && n+m)
	{
		init();
		mapping();
		work();
	}
	return 0;
}


hdu-1814 Peaceful Commission

输出字典序最小的解模板题。

代码:

#include <algorithm>
#include <iostream>
#include <string.h>
#include <vector>
#include <cstdio>
#include <queue> 
using namespace std;
const int maxn = 16005;
const int maxm = 40005;
struct node {int u, v, next;} edge[maxm];
int no, head[maxn];
int col[maxn], sta[maxn], top;
int n, m;
void init()
{
    no = 0;
    memset(head, -1, sizeof head);
    memset(col, 0, sizeof col);
}
inline void add(int u, int v)
{
    edge[no].u = u; edge[no].v = v;
    edge[no].next = head[u]; head[u] = no++;
}
void print()
{
    for(int i = 0; i < n; ++i)
    {
        if(col[i*2] == 1) printf("%d\n", i*2+1);
        if(col[i*2+1] == 1) printf("%d\n", i*2+1+1);
    }
}
bool dfs(int u)
{
    if(col[u^1]) return 0;
    if(col[u]) return 1;
    col[u] = 1;
    sta[++top] = u;
    for(int k = head[u]; k+1; k = edge[k].next)
    {
        int v = edge[k].v;
        if(!dfs(v)) return 0;
    }
    return 1;
}
void work()
{
    for(int i = 0; i < n; ++i)
    {
        if(col[i*2] || col[i*2+1]) continue;
        top = 0;
        if(!dfs(i*2))
        {
            while(top) col[sta[top--]] = 0;
            if(!dfs(i*2+1))
            {
                puts("NIE");
                return;
            }
        }
    }
    print();
}
void mapping()
{
    for(int i = 1; i <= m; ++i)
    {
        int u, v;
        scanf("%d %d", &u, &v);
        --u, --v;
        add(u, (v^1));
        add(v, (u^1));
    }
}
int main()
{
    //freopen("SPO.in", "r", stdin);
    //freopen("SPO.out", "w", stdout);
    while(~scanf("%d %d", &n, &m))
    {
        init();
        mapping();
        work();
    }
    return 0;
}


poj-3678 Katu Puzzle

抽象and、or、xor的冲突建图,求可行解。

代码:

#include <algorithm>
#include <iostream>
#include <string.h>
#include <vector>
#include <cstdio>
#include <queue> 
using namespace std;
const int maxn = 1005;
const int maxm = 4e6+5;
struct node {int u, v, next;} edge[maxm];
int no, head[maxn];
int dfn[maxn], low[maxn], index, sta[maxn], top;
bool vis[maxn];
int bel[maxn], cnt;
int n, m;
void init()
{
	no = 0;
	memset(head, -1, sizeof head);
	index = 0, top = 0;
	memset(dfn, 0, sizeof dfn);
	memset(vis, 0, sizeof vis);
	cnt = 0;
}
inline void add(int u, int v)
{
	edge[no].u = u; edge[no].v = v;
	edge[no].next = head[u]; head[u] = no++;
}
void tarjan(int u)
{
	dfn[u] = low[u] = ++index;
	sta[++top] = u, vis[u] = 1;
	for(int k = head[u]; k+1; k = edge[k].next)
	{
		int v = edge[k].v;
		if(!dfn[v])
		{
			tarjan(v);
			low[u] = min(low[u], low[v]);
		}
		else if(vis[v]) low[u] = min(low[u], dfn[v]);
	}
	if(dfn[u] == low[u])
	{
		++cnt;
		do
		{
			vis[sta[top]] = 0;
			bel[sta[top]] = cnt;
			--top;
		}
		while(sta[top+1] != u);
	}
}
void work()
{
	for(int i = 0; i < n*2; ++i)
	if(!dfn[i]) tarjan(i);
	for(int i = 0; i < n; ++i)
	{
		if(bel[i*2] == bel[i*2+1])
		{
			puts("NO");
			return;
		}
	}
	puts("YES");
}
void mapping()
{
	for(int i = 1; i <= m; ++i)
	{
		int u, v, w;
		char s[5];
		scanf("%d %d %d%s", &u, &v, &w, s);
		u *= 2, v *= 2;
		if(s[0] == 'A')
		{
			if(w == 1) 
			add(u+1, v+1), add(v+1, u+1), add(u, u+1), add(v, v+1);
			else 
			add(u+1, v), add(v+1, u);
		}
		if(s[0] == 'O')
		{
			if(w == 1) 
			add(u, v+1), add(v, u+1);
			else 
			add(u, v), add(v, u), add(u+1, u), add(v+1, v);
		}
		if(s[0] == 'X')
		{
			if(w == 1) 
			add(u, v+1), add(v, u+1), add(v+1, u), add(u+1, v);
			else 
			add(u, v), add(v, u), add(u+1, v+1), add(v+1, u+1);
		}
	}
}
int main()
{
	while(scanf("%d %d", &n, &m) != EOF)
	{
		init();
		mapping();
		work();
	}
	return 0;
}


hdu-3622 Bomb Game

二分构图+可行性判断。

代码:

#include <algorithm>
#include <iostream>
#include <string.h>
#include <vector>
#include <cstdio>
#include <queue> 
#include <cmath>
using namespace std;
const double eps = 1e-5;
const int maxn = 205;
const int maxm = 4*maxn*maxn;
struct node {int u, v, next;} edge[maxm];
int no, head[maxn];
int dfn[maxn], low[maxn], index, sta[maxn], top;
bool vis[maxn];
int bel[maxn], cnt;
int n;
struct coordinate {int x, y;} a[2][maxn];
double dis[4][maxn][maxn];
void init()
{
    no = 0;
    memset(head, -1, sizeof head);
    index = 0, top = 0;
    memset(dfn, 0, sizeof dfn);
    memset(vis, 0, sizeof vis);
    cnt = 0;
}
inline void add(int u, int v)
{
    edge[no].u = u; edge[no].v = v;
    edge[no].next = head[u]; head[u] = no++;
}
void tarjan(int u)
{
    dfn[u] = low[u] = ++index;
    sta[++top] = u, vis[u] = 1;
    for(int k = head[u]; k+1; k = edge[k].next)
    {
        int v = edge[k].v;
        if(!dfn[v])
        {
            tarjan(v);
            low[u] = min(low[u], low[v]);
        }
        else if(vis[v]) low[u] = min(low[u], dfn[v]);
    }
    if(dfn[u] == low[u])
    {
        ++cnt;
        do
        {
            vis[sta[top]] = 0;
            bel[sta[top]] = cnt;
            --top;
        }
        while(sta[top+1] != u);
    }
}
bool work()
{
    for(int i = 0; i < n*2; ++i)
    if(!dfn[i]) tarjan(i);
    for(int i = 0; i < n; ++i)
    {
        if(bel[i*2] == bel[i*2+1])
        return 0;
    }
    return 1;
}
bool mapping(double up)
{
    for(int i = 0; i < n; ++i)
    for(int j = i+1; j < n; ++j)
    {
        if(dis[0][i][j] <= up*up) add(i*2, j*2+1), add(j*2, i*2+1);
        
        if(dis[1][i][j] <= up*up) add(i*2, j*2), add(j*2+1, i*2+1);
        
        if(dis[2][i][j] <= up*up) add(i*2+1, j*2+1), add(j*2, i*2);
        
        if(dis[3][i][j] <= up*up) add(i*2+1, j*2), add(j*2+1, i*2);
    }
    return 1;
}
bool jg(double x)
{
    init();
    if(!mapping(x*2)) return 0;
    return work();
}
int main()
{
    //freopen("in.txt", "r", stdin);
    while(scanf("%d", &n) != EOF)
    {
        for(int i = 0; i < n; ++i)
        {
            scanf("%d %d", &a[0][i].x, &a[0][i].y);
            scanf("%d %d", &a[1][i].x, &a[1][i].y);
        }
        double t, l = 0, r = 0;
        for(int i = 0; i < n; ++i)
        for(int j = i+1; j < n; ++j)
        {
            t = (a[0][i].x-a[0][j].x)*(a[0][i].x-a[0][j].x);
            t += (a[0][i].y-a[0][j].y)*(a[0][i].y-a[0][j].y);
            dis[0][i][j] = t;
            r = max(r, sqrt(t));
            
            t = (a[0][i].x-a[1][j].x)*(a[0][i].x-a[1][j].x);
            t += (a[0][i].y-a[1][j].y)*(a[0][i].y-a[1][j].y);
            dis[1][i][j] = t;
            r = max(r, sqrt(t));
            
            t = (a[1][i].x-a[0][j].x)*(a[1][i].x-a[0][j].x);
            t += (a[1][i].y-a[0][j].y)*(a[1][i].y-a[0][j].y);
            dis[2][i][j] = t;
            r = max(r, sqrt(t));
            
            t = (a[1][i].x-a[1][j].x)*(a[1][i].x-a[1][j].x);
            t += (a[1][i].y-a[1][j].y)*(a[1][i].y-a[1][j].y);
            dis[3][i][j] = t;
            r = max(r, sqrt(t));
        }
        while(r-l > eps)
        {
            double mid = (l+r)/2;
            if(jg(mid)) l = mid;
            else r = mid;
        }
        printf("%.2f\n", l+eps);
    }
    return 0;
}


poj-3207 Ikki's Story IV - Panda's Trick

抽象语义,构图求解可行性。

代码:

#include <algorithm>
#include <iostream>
#include <string.h>
#include <vector>
#include <cstdio>
#include <cmath>
using namespace std;
const int maxn = 1005;
const int maxm = 4*maxn*maxn;
struct node {int u, v, next;} edge[maxm];
int no, head[maxn];
int dfn[maxn], low[maxn], index, sta[maxn], top;
bool vis[maxn];
int bel[maxn], cnt;
int n, m;
struct coordinate {int u, v;} a[maxn];
void init()
{
	no = 0;
	memset(head, -1, sizeof head);
	index = 0, top = 0;
	memset(dfn, 0, sizeof dfn);
	memset(vis, 0, sizeof vis);
	cnt = 0;
}
inline void add(int u, int v)
{
	edge[no].u = u; edge[no].v = v;
	edge[no].next = head[u]; head[u] = no++;
}
void tarjan(int u)
{
	dfn[u] = low[u] = ++index;
	sta[++top] = u, vis[u] = 1;
	for(int k = head[u]; k+1; k = edge[k].next)
	{
		int v = edge[k].v;
		if(!dfn[v])
		{
			tarjan(v);
			low[u] = min(low[u], low[v]);
		}
		else if(vis[v]) low[u] = min(low[u], dfn[v]);
	}
	if(dfn[u] == low[u])
	{
		++cnt;
		do
		{
			vis[sta[top]] = 0;
			bel[sta[top]] = cnt;
			--top;
		}
		while(sta[top+1] != u);
	}
}
bool work()
{
	for(int i = 0; i < m*2; ++i)
	if(!dfn[i]) tarjan(i);
	for(int i = 0; i < m; ++i)
	{
		if(bel[i*2] == bel[i*2+1])
		return 0;
	}
	return 1;
}
void mapping()
{
	for(int i = 0; i < m; ++i)
	{
		scanf("%d %d", &a[i].u, &a[i].v);
		if(a[i].u > a[i].v) swap(a[i].u, a[i].v);
		for(int j = 0; j < i; ++j)
		{
			if(a[i].u < a[j].u && a[i].v > a[j].u && a[i].v < a[j].v)
			add(i*2, j*2+1), add(i*2+1, j*2),
			add(j*2, i*2+1), add(j*2+1, i*2);
			if(a[j].u < a[i].u && a[j].v > a[i].u && a[j].v < a[i].v)
			add(i*2, j*2+1), add(i*2+1, j*2),
			add(j*2, i*2+1), add(j*2+1, i*2);
		}
	}
}
int main()
{
	//freopen("in.txt", "r", stdin);
	while(scanf("%d %d", &n, &m) != EOF)
	{
		init();
		mapping();
		if(work()) puts("panda is telling the truth...");
		else puts("the evil panda is lying again");
	}
	return 0;
}


poj-2296 Map Labeler

二分建图+可行性判断

只说一下哪几个冲突吧:同时不选,必选某点。

代码:

#include <algorithm>
#include <iostream>
#include <string.h>
#include <vector>
#include <cstdio>
using namespace std;
const int maxn = 205;
const int maxm = 4*maxn*maxn;
struct node {int u, v, next;} edge[maxm];
int no, head[maxn];
int dfn[maxn], low[maxn], _index, sta[maxn], top;
bool vis[maxn];
int bel[maxn], cnt;
int t, n;
struct coordinate {int x, y;} a[maxn];
void init()
{
	no = 0;
	memset(head, -1, sizeof head);
	_index = 0, top = 0;
	memset(dfn, 0, sizeof dfn);
	memset(vis, 0, sizeof vis);
	cnt = 0;
}
inline void add(int u, int v)
{
	edge[no].u = u; edge[no].v = v;
	edge[no].next = head[u]; head[u] = no++;
}
void tarjan(int u)
{
	dfn[u] = low[u] = ++_index;
	sta[++top] = u, vis[u] = 1;
	for(int k = head[u]; k+1; k = edge[k].next)
	{
		int v = edge[k].v;
		if(!dfn[v])
		{
			tarjan(v);
			low[u] = min(low[u], low[v]);
		}
		else if(vis[v]) low[u] = min(low[u], dfn[v]);
	}
	if(dfn[u] == low[u])
	{
		++cnt;
		do
		{
			vis[sta[top]] = 0;
			bel[sta[top]] = cnt;
			--top;
		}
		while(sta[top+1] != u);
	}
}
bool work()
{
	for(int i = 0; i < n*2; ++i)
	if(!dfn[i]) tarjan(i);
	for(int i = 0; i < n; ++i)
	{
		if(bel[i*2] == bel[i*2+1])
		return 0;
	}
	return 1;
}
void mapping(int k)
{
	for(int i = 0; i < n; ++i)
	for(int j = 0; j < i; ++j)
	{
		if(abs(a[i].x-a[j].x) >= k) continue;
		if(a[i].y == a[j].y)
		add(i*2, j*2+1), add(j*2, i*2+1), add(i*2+1, j*2), add(j*2+1, i*2);
		if(a[i].y > a[j].y && a[i].y-a[j].y < k)
		add(i*2+1, i*2), add(j*2, j*2+1);
		if(a[j].y > a[i].y && a[j].y-a[i].y < k)
		add(j*2+1, j*2), add(i*2, i*2+1);
		if(a[i].y-a[j].y >= k && a[i].y-a[j].y < 2*k)
		add(i*2+1, j*2+1), add(j*2, i*2);
		if(a[j].y-a[i].y >= k && a[j].y-a[i].y < 2*k)
		add(j*2+1, i*2+1), add(i*2, j*2);
	}
}
bool jg(int k)
{
	init();
	mapping(k);
	return work();
}
int main()
{
	for(scanf("%d", &t); t--;)
	{
		scanf("%d", &n);
		for(int i = 0; i < n; ++i)
		scanf("%d %d", &a[i].x, &a[i].y);
		int l = 1, r = 20000;
		while(l <= r)
		{
			int mid = (l+r)>>1;
			if(jg(mid)) l = mid+1;
			else r = mid-1;
		}
		printf("%d\n", r);
	}
	return 0;
}


像刷kb菊苣的题一样也写点题外话,区域赛前2-SAT就做到这儿了,其实只要能将语义抽象出来2-SAT问题,也能抽象出所有的冲突,2-SAT就很好做了。实力还得再提高啊,路还得走...

继续加油~

相关文章:

  • 64位windows2003 未在本地计算机上注册 microsoft.jet.oledb.4.0 提供程序
  • HDU-5950 Recursive sequence(矩阵乘法)
  • “互联网+”引发IT人才招工荒-新华网安徽频道
  • Java从文件读入以及读出至文件
  • HDU-5963 朋友(树上博弈)
  • HDU 6005 Pandaland(无向图最小环)
  • Cura源码在Ubuntu15.04上编译脚本(成功)
  • SPOJ - CHICAGO 106 miles to Chicago(乘积最短路)
  • HTML5之FileReader的使用
  • LeetCode 202 Happy Number(floyd判圈算法(龟兔赛跑算法))
  • css3 中text-align:justify
  • HDU-1503 Advanced Fruits(LCS)
  • LightOJ-1253 Misere Nim(Nim求解不正常的博弈)
  • python发送电子邮件模块smtplib
  • uva-1349 Optimal Bus Route Design(最小费用最大流)
  • -------------------- 第二讲-------- 第一节------在此给出链表的基本操作
  • @angular/forms 源码解析之双向绑定
  • @jsonView过滤属性
  • 【腾讯Bugly干货分享】从0到1打造直播 App
  • 03Go 类型总结
  • Asm.js的简单介绍
  • DataBase in Android
  • HTML中设置input等文本框为不可操作
  • JAVA多线程机制解析-volatilesynchronized
  • Netty 4.1 源代码学习:线程模型
  • Spring Security中异常上抛机制及对于转型处理的一些感悟
  • vue从创建到完整的饿了么(11)组件的使用(svg图标及watch的简单使用)
  • 道格拉斯-普克 抽稀算法 附javascript实现
  • 基于 Babel 的 npm 包最小化设置
  • 人脸识别最新开发经验demo
  • 什么软件可以剪辑音乐?
  • 我从编程教室毕业
  • 线上 python http server profile 实践
  • 译有关态射的一切
  • kubernetes资源对象--ingress
  • $redis-setphp_redis Set命令,php操作Redis Set函数介绍
  • (C++)栈的链式存储结构(出栈、入栈、判空、遍历、销毁)(数据结构与算法)
  • (Matalb时序预测)WOA-BP鲸鱼算法优化BP神经网络的多维时序回归预测
  • (附源码)ssm基于web技术的医务志愿者管理系统 毕业设计 100910
  • (原)记一次CentOS7 磁盘空间大小异常的解决过程
  • (转载)VS2010/MFC编程入门之三十四(菜单:VS2010菜单资源详解)
  • **CI中自动类加载的用法总结
  • .Family_物联网
  • .FileZilla的使用和主动模式被动模式介绍
  • .Net 4.0并行库实用性演练
  • .NET Core工程编译事件$(TargetDir)变量为空引发的思考
  • .NET/ASP.NETMVC 大型站点架构设计—迁移Model元数据设置项(自定义元数据提供程序)...
  • .NET/C# 项目如何优雅地设置条件编译符号?
  • .net对接阿里云CSB服务
  • .Net下C#针对Excel开发控件汇总(ClosedXML,EPPlus,NPOI)
  • @KafkaListener注解详解(一)| 常用参数详解
  • [Android开源]EasySharedPreferences:优雅的进行SharedPreferences数据存储操作
  • [BUG]vscode插件live server无法自动打开浏览器
  • [DNS网络] 网页无法打开、显示不全、加载卡顿缓慢 | 解决方案
  • [emuch.net]MatrixComputations(7-12)