码迷,mamicode.com
首页 > Web开发 > 详细

BZOJ 1823 JSOI 2010 满汉全席 2-SAT

时间:2014-10-02 11:51:52      阅读:796      评论:0      收藏:0      [点我收藏+]

标签:bzoj   bzoj1823   jsoi2010   2-sat   tarjan   

题目大意:有n种材料,m个评委。每种材料有两种不同的做法,每个评委有两个判定标准,做出来的菜品必须满足每一个评委至少一个要求。问有没有这样的方案。


思路:2-SAT经典建图问题。因为每一种材料只能有两种做法,这种约束条件通常就想到2-SAT。每一个评委必须至少满足一种,这就是建图的条件。

所以连边A‘ -> B

      B’ -> A

这样表示的是如果A不能满足某个评委,那么就必须让b满足这个评委。

然后就是Tarjan缩点,判断是否有个菜品的两种做法在一个scc中,若有就是无解,没有就是有解。


CDOE:


#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 5010
using namespace std;

int cases;
int points,cnt;

int head[MAX],_total;
int _next[MAX],aim[MAX];

int dfn[MAX],low[MAX],total;
int stack[MAX],top;
bool in_stack[MAX];
int changed[MAX],scc;

char c1,c2;

inline void Initialize();
inline void Add(int x,int y);
void Tarjan(int x);

int main()
{
    for(cin >> cases;cases; --cases) {
        scanf("%d%d",&points,&cnt);
        Initialize();
        for(int x,y,i = 1;i <= cnt; ++i) {
            getchar();
            scanf("%c%d %c%d",&c1,&x,&c2,&y);
            x = (x << 1) + (c1 == 'h');
            y = (y << 1) + (c2 == 'h');
            Add(x^1,y);
            Add(y^1,x); 
        }
        for(int i = 2;i <= (points << 1|1); ++i)
            if(!dfn[i]) Tarjan(i);
        bool flag = true;
        for(int i = 1;i <= points; ++i)
        	if(changed[i << 1] == changed[i << 1|1])
        		flag = false;
    	if(flag)	puts("GOOD");
    	else		puts("BAD");
    }
    return 0;
}

inline void Initialize()
{
	total = _total = top = scc =0;
	memset(dfn,0,sizeof(dfn));
	memset(head,0,sizeof(head));
	memset(in_stack,false,sizeof(in_stack));
}

inline void Add(int x,int y)
{
    _next[++_total] = head[x];
    aim[_total] = y;
    head[x] = _total;
}

void Tarjan(int x)
{
    dfn[x] = low[x] = ++total;
    stack[++top] = x;
    in_stack[x] = true;
    for(int i = head[x];i;i = _next[i]) {
        if(!dfn[aim[i]])
            Tarjan(aim[i]),low[x] = min(low[x],low[aim[i]]);
        else if(in_stack[aim[i]])
        	low[x] = min(low[x],dfn[aim[i]]);
    }
    if(low[x] == dfn[x]) {
    	scc++;
    	int temp;
    	do {
    		temp = stack[top--];
    		changed[temp] = scc;
    		in_stack[temp] = false;
    	}while(temp != x);
    }
}


BZOJ 1823 JSOI 2010 满汉全席 2-SAT

标签:bzoj   bzoj1823   jsoi2010   2-sat   tarjan   

原文地址:http://blog.csdn.net/jiangyuze831/article/details/39735251

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!