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
  • 相关阅读:
    Leetcode Reverse Words in a String
    topcoder SRM 619 DIV2 GoodCompanyDivTwo
    topcoder SRM 618 DIV2 MovingRooksDiv2
    topcoder SRM 618 DIV2 WritingWords
    topcoder SRM 618 DIV2 LongWordsDiv2
    Zepto Code Rush 2014 A. Feed with Candy
    Zepto Code Rush 2014 B
    Codeforces Round #245 (Div. 2) B
    Codeforces Round #245 (Div. 2) A
    Codeforces Round #247 (Div. 2) B
  • 原文地址:https://www.cnblogs.com/edmunds/p/12908734.html
Copyright © 2011-2022 走看看