zoukankan      html  css  js  c++  java
  • 洛谷P1955 程序自动分析 离散化+并查集

    题目链接: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
  • 相关阅读:
    Mysql主外键
    行列转换
    简单的增删改查
    day22 面向对象基础
    day21 xml模块 ATM+购物车
    python学习 day19 configparser模块 os模块 subprocess模块
    day18 logging模块 sys shelve
    day17 正则表达式 re模块和hashlib模块
    day16 包的使用 json time 常用模块
    day15模块内容
  • 原文地址:https://www.cnblogs.com/edmunds/p/12908734.html
Copyright © 2011-2022 走看看