P1955 程序自动分析
解题思路:
容易想到用扩展域做
- "=":朋友
- "≠":敌人
实际上不需要:
利用等价关系具有传递性
- 先处理
e=1的条件 - 在处理
e=0判断是否冲突
注意:
输入的i,j不再是编号1~N,而是1~1e9!——离散化
补充说明:
//样例
10
1 2 1
2 3 1
3 5 1
5 10 1
10 100 1
10000 100 1
1 9999 0
3 2 1
10000 1 0
2 3 1
//离散化结果(偏移量+1之后:)
idx 1 2 3 4 5 6 7 8
val 1 2 3 5 10 100 9999 10000
//对应原式fa[i]
fa 1 2 3 4 5 6 7 8
代码:
struct edge{int x,y,e;};
vector<edge> ed(N);//关系数组
int t,fa[2*N],n,n2,fx,fy,ix,iy;
bool flag;
int find(int x){
if(fa[x]==x) return x;
else return fa[x]=find(fa[x]);
}
void unionset(int a,int b){
fa[find(a)]=find(b);
}
bool cmp(edge ed1,edge ed2){
return ed1.e>ed2.e;//先处理"="
}
int main(){
cin>>t;
for(int i=0;i<t;++i){
flag=true;
vector<int> v;//离散化数组
cin>>n;
for(int j=0;j<n;++j){
cin>>ed[j].x>>ed[j].y>>ed[j].e;
v.push_back(ed[j].x);
v.push_back(ed[j].y);
}
sort(ed.begin(),ed.begin()+n,cmp);
sort(v.begin(),v.end());
auto it=unique(v.begin(),v.end());
v.erase(it,v.end());
n2=v.size();//去重后的元素个数
for(int j=1;j<=n2;++j) fa[j]=j;//fa[1-n2]
for(int j=0;j<n;++j){
ix=distance(v.begin(),lower_bound(v.begin(),v.end(),ed[j].x))+1;//获得离散化后的下标
iy=distance(v.begin(),lower_bound(v.begin(),v.end(),ed[j].y))+1;//获得离散化后的下标
if(ed[j].e==1) unionset(ix,iy);
else{
fx=find(ix);
fy=find(iy);
if(fx==fy){//冲突
flag=false;
break;
}
}
}
if(flag) cout<<"YES\n";
else cout<<"NO\n";
}
return 0;
}

浙公网安备 33010602011771号