洛谷P1955 [noi2015]程序自动分析 离散化+并查集

题目链接:https://www.luogu.com.cn/problem/P1955

题意就是给定n个相等和不等关系xi=xj或xi≠xj,判定所有条件是否能被满足。n<=1e6且xi<=1e9。

应该能看出来是个并查集。如果在线判断的话似乎不太好做(不会= =),因为不等号没有传递性。所以先处理所有的等号关系,相等的话两个元素就属于同一集合。最后再处理所有不等号关系,如果不相等的元素在同一集合里就错误。注意xi的范围<=1e9,不可能开这么大的并查集数组,所以需要离散化。第一次使用了map来离散化,想法是很简单但是不开O2的话第二个点是会tle的,大概是因为map常数太大......附上map离散化的代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int maxn=1000+10;
 5 struct st{    int x,y;};
 6 vector<st> b; //存不等关系 
 7 map<int,int> mp; //离散化 
 8 int par[2*maxn];
 9 int n,i,j,t,num,k;
10 
11 int find(int x){return x==par[x]?x:par[x]=find(par[x]);};
12 
13 int main(){
14     std::ios::sync_with_stdio(false);
15     //freopen("luogu1955.txt","r",stdin);
16     cin>>t;
17     while (t--){
18         mp.clear();num=0;b.clear();
19         cin>>n;
20         for (i=1;i<=2*n;i++) par[i]=i;
21         for (i=1;i<=n;i++){
22             int p,q,e;
23             cin>>p>>q>>e;
24             if (mp[p]==0) mp[p]=(++num); //*
25             if (mp[q]==0) mp[q]=(++num);
26             if (e==1){ //p,q相等 
27                 int xx=find(mp[p]);int yy=find(mp[q]);
28                 if (xx!=yy) par[xx]=yy;
29             }
30             else{
31                 st a;
32                 a.x=mp[p];a.y=mp[q];
33                 b.push_back(a);
34             }
35         }
36         int f=0;
37         for (i=1;i<=num;i++) par[i]=find(i);
38         for (i=0;i<b.size();i++)
39           if (par[b[i].x]==par[b[i].y]){
40               cout<<"NO"<<endl;
41               f=1; break;
42           }
43         if (f==0) cout<<"YES"<<endl; 
44     }
45     //fclose(stdin);
46     return 0;
47 }
洛谷1955_1

 

之后用了另外一种方法写离散化,参考这篇博客:https://www.cnblogs.com/cytus/p/8933597.html。这么写的话虽然复杂度还是O(nlogn)的,但是可以不开O2就通过了,比map大约快了2s多。看了下提交记录,很好奇那些120ms的神仙是怎么做到的= =

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int maxn=1000+10;
 5 struct st{int x,y,e;}a[maxn];
 6 int b[maxn*2],par[maxn*2];
 7 int n,i,j,k,t;
 8 
 9 int find(int x){return (par[x]==x)?x:par[x]=find(par[x]);};
10 
11 int main(){
12     std::ios::sync_with_stdio(false);
13     cin>>t;
14     while (t--){
15         cin>>n;
16         int cnt=0;
17         for (i=1;i<=n;i++){
18             cin>>a[i].x;b[++cnt]=a[i].x;
19             cin>>a[i].y;b[++cnt]=a[i].y;
20             cin>>a[i].e;
21         }
22         sort(b+1,b+cnt+1);
23         int m=unique(b+1,b+cnt+1)-b-1;
24         for (i=1;i<=n;i++){
25             a[i].x=lower_bound(b+1,b+m+1,a[i].x)-b;
26             a[i].y=lower_bound(b+1,b+m+1,a[i].y)-b;
27         }
28         for (i=1;i<=n*2;i++) par[i]=i;
29         for (i=1;i<=n;i++)
30           if (a[i].e==1) {
31             int xx=find(a[i].x);int yy=find(a[i].y);
32             if (xx!=yy) par[xx]=yy;
33           }
34         for (i=1;i<=2*n;i++) par[i]=find(par[i]);
35         int f=0;
36         for (i=1;i<=n;i++)
37           if (a[i].e==0&&par[a[i].x]==par[a[i].y]){
38               cout<<"NO"<<endl;f=1;break;
39           }
40         if (f==0) cout<<"YES"<<endl;
41     }
42     return 0;
43 }
洛谷1955_2

 

posted @ 2020-05-18 09:25  coastal_taipan  阅读(188)  评论(0编辑  收藏  举报