• AtCoder Beginner Contest 131 F


    题意:给出二维平面的n个点坐标,定义一种操作:若恰好三个点能形成一个矩形(当然这个矩形会缺了一个点),那么就在图上添加这个缺的点,问在原图上最多能进行几次这样的操作。

    解法:这题想了挺久没想到,一看题解发现z自己思路和正解完全不沾边(尴尬)。解法参考https://www.cnblogs.com/zaq19970105/p/11108175.html这位大佬的。我们把x轴看作二分图的左边点,y轴看作二分图右边点,对于原图上的点就向左边点向右边点连边,即二分图一条边就是原图一个点。然后我们先观察四个点能构成矩形有什么特点:如果在二分图上左边任意两个点和任意右边两个点有4条连边就是能构成矩形,那么怎么才是缺一个点呢?基于上面就不难想了,就是左两个点和右两个点只有3条边,那么缺的那一条边就是缺的点。然后接下来这个发现就难一点了,就是如果左两个点右两个点至少有3条边相连,那么这四个点就必须是连通的(而若只有两条边就不会)。那么按原图在二分图进行连边之后就会出现一个个联通块,进行一次题目操作就会在联通块上加一条边,直到加到不能加就是完全二分图为止。那么答案就出来了:就是每个联通块完全图边数-原图已有的边数 ,所有联通块加起来就是答案。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int N=2e5+10;
     4 typedef long long LL;
     5 int n,X,Y;
     6 vector<int> G[N],v;
     7 bool vis[N];
     8 
     9 void dfs(int x,int dep) {
    10     if (dep%2) X++; else Y++;
    11     v.push_back(x);
    12     vis[x]=1;
    13     for (int i=0;i<G[x].size();i++) {
    14         int t=G[x][i];
    15         if (vis[t]) continue;
    16         dfs(t,dep+1);
    17     }
    18 }
    19 
    20 int main()
    21 {
    22     cin>>n;
    23     for (int i=1;i<=n;i++) {
    24         int x,y; scanf("%d%d",&x,&y);
    25         G[x].push_back(y+100000);
    26         G[y+100000].push_back(x);
    27     }
    28     
    29     memset(vis,0,sizeof(vis));
    30     LL ans=0;
    31     for (int i=1;i<=200000;i++) 
    32         if (G[i].size() && !vis[i]) {
    33             X=0; Y=0; v.clear();
    34             dfs(i,1);
    35             LL num=0;
    36             for (int j=0;j<v.size();j++) num+=G[v[j]].size();
    37             ans+=(LL)X*Y-num/2;
    38         }
    39     cout<<ans<<endl;    
    40     return 0;
    41 }
  • 相关阅读:
    web.xml
    ibatis配置
    ibatis基本语法
    XML文件解析
    进制转换
    BaseAction
    【编译】StreamInsight简介
    秒懂C#通过Emit动态生成代码
    百度地图应用开发(二)
    ListView与Adapter的那些事儿
  • 原文地址:https://www.cnblogs.com/clno1/p/11224028.html
Copyright © 2020-2023  润新知