• Codeforces 870E Points, Lines and Ready-made Titles:并查集【两个属性二选一】


    题目链接:http://codeforces.com/problemset/problem/870/E

    题意:

      给出平面坐标系上的n个点。

      对于每个点,你可以画一条经过这个点的横线或竖线或什么都不画。

      两条重合的直线算作一条直线。

      问你能画出多少种不同的图案。

    题解:

      将所有横坐标或纵坐标相同的两点之间连边。

      对于一个连通块,设这个连通块中不同的横坐标个数为sx,不同的纵坐标个数为sy。

      有可能画出的线的个数即为sx + sy。

      可以发现,如果一个联通块中有环(即siz[fa] >= sx + sy)

      那么这sx + sy条边可以同时画出。

      否则必然有一条边不能画出。

      所以当前连通块的答案:有环为2^(sx+sy),无环为2^(sx+sy) - 1。

      将所有连通块的答案乘起来即为总答案。

    AC Code:

      1 #include <iostream>
      2 #include <stdio.h>
      3 #include <string.h>
      4 #include <algorithm>
      5 #include <set>
      6 #define MAX_N 100005
      7 #define MAX_E 200005
      8 #define MOD 1000000007
      9 
     10 using namespace std;
     11 
     12 struct Coor
     13 {
     14     int x,y,id;
     15     Coor(int _x,int _y,int _id)
     16     {
     17         x=_x; y=_y; id=_id;
     18     }
     19     Coor(){}
     20 };
     21 
     22 int n;
     23 int par[MAX_N];
     24 int siz[MAX_N];
     25 long long ans=1;
     26 long long pw[MAX_E];
     27 Coor c[MAX_N];
     28 set<int> sx[MAX_N];
     29 set<int> sy[MAX_N];
     30 
     31 bool cmp1(const Coor &a,const Coor &b)
     32 {
     33     return a.y!=b.y ? a.y<b.y : a.x<b.x;
     34 }
     35 
     36 bool cmp2(const Coor &a,const Coor &b)
     37 {
     38     return a.x!=b.x ? a.x<b.x : a.y<b.y;
     39 }
     40 
     41 void read()
     42 {
     43     cin>>n;
     44     for(int i=1;i<=n;i++)
     45     {
     46         cin>>c[i].x>>c[i].y;
     47         c[i].id=i;
     48     }
     49 }
     50 
     51 void init_union_find()
     52 {
     53     for(int i=1;i<=n;i++)
     54     {
     55         par[i]=i;
     56         siz[i]=1;
     57     }
     58 }
     59 
     60 int find(int x)
     61 {
     62     return par[x]==x ? x : par[x]=find(par[x]);
     63 }
     64 
     65 void unite(int x,int y)
     66 {
     67     int px=find(x);
     68     int py=find(y);
     69     if(px==py) return;
     70     siz[py]+=siz[px];
     71     par[px]=py;
     72 }
     73 
     74 void build()
     75 {
     76     sort(c+1,c+1+n,cmp1);
     77     for(int i=1;i<n;i++)
     78     {
     79         if(c[i].y==c[i+1].y)
     80         {
     81             unite(c[i].id,c[i+1].id);
     82         }
     83     }
     84     sort(c+1,c+1+n,cmp2);
     85     for(int i=1;i<n;i++)
     86     {
     87         if(c[i].x==c[i+1].x)
     88         {
     89             unite(c[i].id,c[i+1].id);
     90         }
     91     }
     92 }
     93 
     94 void cal_pow()
     95 {
     96     pw[0]=1;
     97     for(int i=1;i<MAX_E;i++) pw[i]=(pw[i-1]<<1ll)%MOD;
     98 }
     99 
    100 void cal_set()
    101 {
    102     for(int i=1;i<=n;i++)
    103     {
    104         sx[find(c[i].id)].insert(c[i].x);
    105         sy[find(c[i].id)].insert(c[i].y);
    106     }
    107 }
    108 
    109 inline long long mod(long long x)
    110 {
    111     return (x%MOD+MOD)%MOD;
    112 }
    113 
    114 void cal_ans()
    115 {
    116     for(int i=1;i<=n;i++)
    117     {
    118         int fa=find(i);
    119         if(fa==i)
    120         {
    121             int edge=sx[fa].size()+sy[fa].size();
    122             if(siz[fa]>=edge) ans=mod(ans*mod(pw[edge]));
    123             else ans=mod(ans*mod(pw[edge]-1));
    124         }
    125     }
    126 }
    127 
    128 void work()
    129 {
    130     init_union_find();
    131     build();
    132     cal_pow();
    133     cal_set();
    134     cal_ans();
    135     cout<<ans<<endl;
    136 }
    137 
    138 int main()
    139 {
    140     read();
    141     work();
    142 }
  • 相关阅读:
    马士兵讲jsp项目--BBS项目分析笔记
    ubuntu 14.04中安装phpmyadmin即mysql图形管理界面
    Xman冬令营writeup
    python--gevent协程及协程概念
    python--multiprocessing多进程总结
    python--threading多线程总结
    浅析Java中print、printf、println的区别
    内存泄漏与内存溢出
    Java中==和equals的区别,equals和hashCode的区别
    vue五十七:电影院售票项目案例之使用swiper实现轮播功能
  • 原文地址:https://www.cnblogs.com/Leohh/p/8468731.html
Copyright © 2020-2023  润新知