洛谷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 }
之后用了另外一种方法写离散化,参考这篇博客: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 }