[BZOJ 4195]程序自动分析
转载请注明出处:http://danihao123.is-programmer.com/
看起来是道并查集水题……
可i和j最高可达1000000000,直接开个数组放注定会MLE,怎么办?
注意n最高为1000000,所以每组数据中出现的i和j最多会有2000000种,所以我们可以把i和j“映射”为不大于2000000的整数,这样就能避免MLE了!
这种技术,就是离散化
同时注意防卡常!
代码:
/**************************************************************
Problem: 4195
User: danihao123
Language: C++
Result: Accepted
Time:1628 ms
Memory:4812 kb
****************************************************************/
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cctype>
using namespace std;
const int maxn=200000; // 常量
/*
并查集
*/
int p[maxn],rank[maxn];
int find_set(int x){
if(p[x]==x)
return x;
else
return p[x]=find_set(p[x]);
}
inline void link(int x,int y){
if(rank[x]>rank[y]){
p[y]=x;
}else{
p[x]=y;
if(rank[x]==rank[y])
rank[y]++;
}
return;
}
void merge_set(int x,int y){
link(find_set(x),find_set(y));
return;
}
bool is_same(int x,int y){
return find_set(x)==find_set(y);
}
inline void init_set(int n){
for(register int i=0;i<n;i++)
p[i]=i;
memset(rank,0,sizeof(rank));
return;
}
// 离散化
int A[maxn],a[maxn],b[maxn];
void init_lsh(int n){
memcpy(b,A,sizeof(A));
sort(A,A+n);
register int size=unique(A,A+n)-A;
for(register int i=0;i<n;i++)
a[i]=lower_bound(A,A+n,b[i])-A;
}
// 解决问题
bool is_is[maxn/2];
void solve(int n){
register int i;
bool ok=true;
init_lsh(2*n);
init_set(2*n);
for(i=0;i<n;i++)
if(is_is[i])
merge_set(a[i*2],a[i*2+1]);
for(i=0;i<n;i++)
if(!is_is[i] && is_same(a[i*2],a[i*2+1])){
ok=false;
puts("NO");
break;
}
if(ok)
puts("YES");
return;
}
inline int readint(){
char c=getchar();
register int x=0;
while(!isdigit(c))
c=getchar();
while(isdigit(c)){
x=x*10+c-'0';
c=getchar();
}
return x;
}
int read_data(){
register int i,n=readint();
for(i=0;i<n;i++){
A[i*2]=readint();
A[i*2+1]=readint();
is_is[i]=readint();
}
return n;
}
int main(){
register int i,n,t=readint();
for(i=0;i<t;i++){
n=read_data();
solve(n);
}
return 0;
}
评论 (0)