P1955 [NOI2015] 程序自动分析

[NOI2015] 程序自动分析

题目简述

输入的第一行包含一个正整数 \(t\),表示需要判定的问题个数。注意这些问题之间是相互独立的。

对于每个问题,包含若干行:

第一行包含一个正整数 \(n\),表示该问题中需要被满足的约束条件个数。接下来 \(n\) 行,每行包括三个整数 \(i,j,e\),描述一个相等/不等的约束条件,相邻整数之间用单个空格隔开。若 \(e=1\),则该约束条件为 \(x_i=x_j\)。若\(e=0\),则该约束条件为 \(x_i\neq x_j\)


思路

题目本身不难,但可以从中学习一点离散化以及哈希表相关的知识(还是不戳滴)
哈希表思路详见

代码

方法一(离散化)

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
struct Node {
  int x,y,op;
}s[N];
int fa[N*2],kdl[N*2];
bool cmp(Node x,Node y){
  return x.op>y.op;
}
inline void in(int &x){
  x=0;
  int f=1;
  char c=getchar();
  while(c<'0'||c>'9'){
    if(c=='-')f=-1;
    c=getchar();
  } 
  while(c>='0'&&c<='9'){
    x=(x<<1)+(x<<3)+c-'0';
    c=getchar();
  }
  x*=f;
}
inline int get_fa(int x){
  return (x==fa[x])?x:(fa[x]=get_fa(fa[x]));
}
int main(){
  freopen("1955.in","r",stdin);
  freopen("1955.out","w",stdout);
  int t;
  in(t);
  while(t--){
    int n;
    bool ok=1;
    in(n);
    int cnt=0;
    for(int i=1;i<=n;i++){
      in(s[i].x);in(s[i].y);in(s[i].op);
      kdl[++cnt]=s[i].x;
      kdl[++cnt]=s[i].y;
    }
    sort(kdl+1,kdl+1+cnt);
    sort(s+1,s+1+n,cmp);
    int tot=unique(kdl+1,kdl+1+cnt)-kdl-1;
    for(int i=1;i<=n;i++){
      s[i].x=lower_bound(kdl+1,kdl+1+tot,s[i].x)-kdl;
      s[i].y=lower_bound(kdl+1,kdl+1+tot,s[i].y)-kdl;
      fa[s[i].x]=s[i].x,fa[s[i].y]=s[i].y;
    }
    for(int i=1;i<=n;i++){
      switch(s[i].op){
        case 1:{
          int fx=get_fa(s[i].x),fy=get_fa(s[i].y);
          fa[fx]=fy;
          break;
        }
        case 0:{
          int fx=get_fa(s[i].x),fy=get_fa(s[i].y);
          if(fx==fy){
            ok=0;
            puts("NO");
          }
          break;
        }
      }
      if(!ok)break; 
    }
    if(ok)
      puts("YES");
  }
  return 0;
}

方法二(哈希表)(代码并非笔者所写qwq)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector> 
#define Max 100010
#define mod 99991 

using namespace std;

int fa[2*Max],d[2*Max];
struct node{
    int real,map;
}un[Max];
vector <node> hash[Max]; 
int tot,cnt;
int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
int ask(int i,int j,bool k)
{
    if(find(i)==find(j)) return 1;
    else if(k){
        fa[find(j)] = find(i);
        return 0;
    }
    return 0;
}
int map(int i,int j,bool k)
{
    int x,y,ok=1;
    int a = i % mod, b = j % mod;
    if(!hash[a].empty()){
        for(int l = 0; l < hash[a].size(); l++)
            if(i==hash[a][l].real) x = hash[a][l].map,ok = 0;
        if(ok) hash[a].push_back((node){i,++tot}),x = tot;
    }
    else hash[a].push_back((node){i,++tot}),x = tot;
    ok = 1;
    if(!hash[b].empty()){
        for(int l = 0; l < hash[b].size(); l++)
            if(j==hash[b][l].real) y = hash[b][l].map,ok = 0;
        if(ok) hash[b].push_back((node){j,++tot}),y = tot;
    }
    else hash[b].push_back((node){j,++tot}),y = tot;
    return ask(x,y,k); 
}
int main()
{
    int n;
    cin >> n;

    for(int i = 1; i <= n; i++)
    {
        for(int i = 1; i <= 200010; i++)
            fa[i] = i;
        for(int i = 0; i < 100000; i++)
            hash[i].clear();
        memset(d,0,sizeof(d));
        memset(un,0,sizeof(un));
        //以上每步的初始化不能丢
        cnt = tot = 0;
        int num,now = 1;
        cin >> num;
        for(int i = 1; i <= num; i++)
        {
            int x,y,z;
            cin >> x >> y >> z;
            if(z) map(x,y,1);
            else un[++cnt].real = x, un[cnt].map = y;   
        }
        for(int i = 1; i <= cnt; i++)
            if(map(un[i].real,un[i].map,0)){
                now = 0;
                cout << "NO" <<endl;
                break;
            }
        if(now) cout << "YES" << endl;
    }
    return 0;
}
posted @ 2023-01-01 18:37  paper_plane  阅读(40)  评论(0)    收藏  举报