zoukankan      html  css  js  c++  java
  • BZOJ 1823 JSOI 2010 盛宴 2-SAT

    标题效果:有着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);
        }
    }


    版权声明:本文博主原创文章,博客,未经同意不得转载。

  • 相关阅读:
    AutoCAD LISP矩形窗格绘制
    AutoCAD VBA多重延伸
    2011年3月24日星期四
    AutoCAD VBA对齐对象
    AutoCAD VBA根据对象缩放
    AutoCAD LISP绘制多个等半径圆相切
    AutoCAD LISP利用一顶点和三边长绘制三角形
    AutoCAD VBA对象的组合和拆散
    AutoCAD LISP修改已存在圆半径
    AutoCAD VBA基于对象的分层
  • 原文地址:https://www.cnblogs.com/bhlsheji/p/4875900.html
Copyright © 2011-2022 走看看