zoukankan      html  css  js  c++  java
  • luogu题解 P4171 【[JSOI2010]满汉全席】

    写在前面

    不会吧不会吧,这么裸的2-SAT都看不出来? 经验题

    题目传送门

    Solution

    2-SAT处理

    关于什么是2-SAT,详见Oiwiki

    简单来说,2-SAT问题的形式是给一堆条件,每个条件中有两个小条件,不过只需要满足其中一种

    题目中说评委的两个条件只需要满足一个即可,然后每种材料又有满式和汉式两种选择

    这不显然让我们打2-SAT?可能也有其他神仙做法

    而2-SAT主要考察建图这一块,我们用 \(0 \sim n\) 表示满式,用 \(n+1 \sim 2n\) 表示汉式,用 \(x^{-1}\) 表示 \(x\) 的另一种菜式

    那么对于任意一个条件 \((a_i,b_i)\)

    • 首先让我们满足 \(a_i\) 而不满足 \(b_i\) ,那就从 \(a_i\)\(b_i^{-1}\) 连一条边

    • 然后让我们满足 \(b_i\) 而不满足 \(a_i\) ,那就从 \(b_i\)\(a_i^{-1}\) 连一条边

    (别搞混了调半天)

    字符串处理

    暴力处理即可,判断第一个字符确定满式还是汉式

    扫一遍字符串取出是第几号菜,然后按上面的方式加边

    答案判断

    用强连通分量缩点

    缩点后,如果存在同一菜品出现在同一强联通分量里,那就不能满足

    否则就可以满足

    大体思路就这些,看代码吧

    Code

    /*
    Work by: Suzt_ilymics
    Knowledge: ??
    Time: O(??)
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define LL long long
    #define orz cout<<"lkp AK IOI!"<<endl
    
    using namespace std;
    const int MAXN = 1e5+5;
    const int INF = 1e9+7;
    const int mod = 1e9+7;
    
    struct edge{
    	int to, nxt;
    }e[MAXN << 1];
    int head[MAXN], num_edge = 0;
    
    int T, n, m;
    int dfn[MAXN], low[MAXN], cnt = 0, stc[MAXN], sc = 0;
    int num[MAXN], t = 0;
    bool vis[MAXN];
    
    int read(){
    	int s = 0, f = 0;
    	char ch = getchar();
    	while(!isdigit(ch))  f |= (ch == '-'), ch = getchar();
    	while(isdigit(ch)) s = (s << 1) + (s << 3) + ch - '0' , ch = getchar();
    	return f ? -s : s;
    }
    
    void add_edge(int from, int to){ e[++num_edge] = (edge){to, head[from]}, head[from] = num_edge; }
    
    void tarjan(int u){
    	stc[++sc] = u, dfn[u] = low[u] = ++cnt, vis[u] = true;
    	for(int i = head[u]; i; i = e[i].nxt){
    		int v = e[i].to;
    		if(!dfn[v]){
    			tarjan(v), low[u] = min(low[u], low[v]);
    		}
    		else if(vis[v]) low[u] = min(low[u], dfn[v]);
    	}
    	if(low[u] == dfn[u]){
    		int pre; ++t;
    		do{
    			pre = stc[sc--];
    			vis[pre] = false;
    			num[pre] = t;
    		}while(pre != u);
    	}
    }
    
    int main()
    {
    	T = read();
    	while(T--){
    		memset(head, 0, sizeof head);
    		memset(vis, false, sizeof vis);
    		memset(dfn, 0, sizeof dfn);
    		num_edge = t = sc = cnt = 0;
    		n = read(), m = read();
    		char u[9], v[9];
    		for(int i = 1; i <= m; ++i){
    //			top = 0;
    //			while(true){
    //				ch = getchar();
    ////				cout<<ch<<endl;
    //				if(ch == ' ') break;
    //				else u[++top] = ch;
    //			}
    //			top = 0;
    //			while(true){
    //				ch = getchar();
    //				if(ch == '\n') break;
    //				else v[++top] = ch;
    //				cout<<ch<<" ";
    //			}
    			cin >>(u + 1)>>(v + 1);
    //			cout<<(u + 1)<<" "<<(v + 1)<<endl;;
    			int u_ = 0, v_ = 0;
    			for(int j = 2; j <= (int)strlen(u + 1); ++j) u_ = (u_ << 1) + (u_ << 3) + (int)(u[j] ^ 48);
    			for(int j = 2; j <= (int)strlen(v + 1); ++j) v_ = (v_ << 1) + (v_ << 3) + (int)(v[j] ^ 48);
    			if(u[1] == 'm' && v[1] == 'm') add_edge(u_, v_ + n), add_edge(v_, u_ + n);	
    			if(u[1] == 'h' && v[1] == 'm') add_edge(u_ + n, v_ + n), add_edge(v_, u_);
    			if(u[1] == 'm' && v[1] == 'h') add_edge(u_, v_), add_edge(v_ + n, u_ + n);
    			if(u[1] == 'h' && v[1] == 'h') add_edge(u_ + n, v_), add_edge(v_ + n, u_);
    		}
    		for(int i = 1; i <= 2 * n; ++i){
    			if(!dfn[i]) tarjan(i);
    		}
    		int flag = false;
    		for(int i = 1;  i <= n; ++i){
    			if(num[i] == num[i + n]){
    				flag = true;
    			}
    		}
    		if(flag) printf("BAD\n");
    		else printf("GOOD\n");
    	}
    	return 0;
    }
    

    如果有什么问题,请在评论区指正

  • 相关阅读:
    CPP--关于long的争议和思考
    CPP--借助神器VS理解内存存储(含大小端对齐)
    1.QT开发第一个程序
    POJ-1456 Supermarket 贪心问题 有时间限制的最小化惩罚问题
    HDU-4310 Hero 贪心问题
    HDU-1789 Doing Homework again 贪心问题 有时间限制的最小化惩罚问题
    HDU-2303 The Embarrassed Cryptographer 高精度算法(大数取模)
    【错题本】刷算法题中出现的一些错误和小技巧
    HDU-2050 折线分割平面 找规律&递推
    记intel杯比赛中各种bug与debug【其五】:朴素贝叶斯分类器的实现和针对性的优化
  • 原文地址:https://www.cnblogs.com/Silymtics/p/14365393.html
Copyright © 2011-2022 走看看