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

    什么,tarjan?那是什么?

    码量太大,我选择放弃

    为什么不用dfs写2-sat呢?他会伤心的说

    这题2-sat的过程大佬们已经讲得非常清楚了,我就略微提一下,主要讲dfs的原理

    2_sat原理

    我们知道,如果要求 (a)(b) , 那么如果 (a) 不成立,我们可以保证 (b) 成立.

    换成式子: (a||b) = (!a&&b) || (a&&!b)

    于是,我们只需要将!a和b连边,!b和a连边就能确定必然要走的路线

    dfs原理

    dfs的原理是对于每个点,我们将所有能拿的边都拿了,然后判断是否满足某一个点 (a) 必然要使得另外一点要同时满足 (b)(!b) .如果存在这样的一个点,那么这个图必然不成立

    具体实现

    首先是连边:

    for (int i=0;i<m;i++){
          string s1,s2; cin >> s1 >> s2;
          int b = (s1[0]=='m') ? 1 : 0, d = (s2[0]=='m') ? 1 : 0;
          int a = get_num(s1),c = get_num(s2);//get_num是将这个string后面的数字转化为int
          adj[a+((b+1)%2)*n].push_back(c+n*d);
          adj[c+((d+1)%2)*n].push_back(a+b*n);
        }
    

    然后正常dfs

    bool dfs(int posi){
      memset(vis,0,sizeof(vis));
      queue<int> q;
      q.push(posi);
      vis[posi] = true;
      while (!q.empty()){
        int qf = q.front();q.pop();
        for (int v : adj[qf]){
          if (!vis[v]){
            vis[v] = true;//没去过下标
            q.push(v);
          }
        }
      }
      for (int i=1;i<=n;i++) if (vis[i] && vis[i+n]) return false;//这里相当于b&!b,因为i+n代表的是!i
      return true;
    }
    

    然后呢?

    然后就完了啊

    其实就对每个点判断是否成立就好了

    完整代码:

    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <vector>
    #include <cstring>
    #include <math.h>
    using namespace std;
    #define pp pair<int,int>
    int n,m,pos[100005];
    vector<int> adj[200005];
    bool vis[200005];
    bool dfs(int posi){
      memset(vis,0,sizeof(vis));
      queue<int> q;
      q.push(posi);
      vis[posi] = true;
      while (!q.empty()){
        int qf = q.front();q.pop();
        for (int v : adj[qf]){
          if (!vis[v]){
            vis[v] = true;
            q.push(v);
          }
        }
      }
      for (int i=1;i<=n;i++) if (vis[i] && vis[i+n]) return false;
      return true;
    }
    int get_num(string s){
      int tmp = 0;
      for (int i=s.length()-1;i>=1;i--){
        tmp+=(int)(s[i]-48)*pow(10,(int)s.length()-i-1);
      }//从右往左拿数
      return tmp;
    }
    int main(){
      int T; cin >> T;
      while(T--){
    
        cin >> n >> m;
        for (int i=1;i<=n*2;i++) adj[i].clear();
        for (int i=0;i<m;i++){
          string s1,s2; cin >> s1 >> s2;
          int b = (s1[0]=='m') ? 1 : 0, d = (s2[0]=='m') ? 1 : 0;//满汉的情况下b是1,否则是2
          int a = get_num(s1),c = get_num(s2);
          adj[a+((b+1)%2)*n].push_back(c+n*d);//a+((b+1)%2)*n表示!a
          adj[c+((d+1)%2)*n].push_back(a+b*n);
        }
        for (int i=1;i<=n;i++) { if(!dfs(i) && !dfs(i+n)){ cout << "BAD" << endl;goto abcd;//有一个跑不了就输出BAD然后走人} }
        cout << "GOOD" << endl;//到这还没走人就是可以输出
        abcd:;
      }
    
    }
    
    

    好题(双倍经验?):P3007

    建议刷完这题去写,难度基本上一样,加几行多一题紫题不好么

  • 相关阅读:
    使用pickle进行存储变量
    tensorflow的save和restore
    使用tf.print()打印tensor内容
    用python对txt中文件读取,然后按顺序标号存入excel中
    cv2对图像进行旋转和放缩变换
    spring security 允许 iframe 嵌套
    Java+protobuf 实例
    Java处理文件小例子--获取全国所有城市的坐标
    Java 多线程并发 Future+callable 实例
    Java 执行jar linux 实例
  • 原文地址:https://www.cnblogs.com/DannyXu/p/12299521.html
Copyright © 2011-2022 走看看