[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;
}
标签:P1955,hash,int,++,tot,NOI2015,自动,return,find
From: https://www.cnblogs.com/fleabag/p/17018407.html