专题突破三之并查集Ⅱ——星球大战,In Touch,方格染色,Junk-Mail Filter,关押罪犯,Silver Woods,Must Be Rectangular!

文章目录

  • [JSOI2008]星球大战
  • In Touch
  • 方格染色
  • Junk-Mail Filter
  • [NOIP2010 提高组] 关押罪犯
  • Silver Woods
  • Must Be Rectangular!

[JSOI2008]星球大战

source

非常套路的,正着打击星球,逆着就是添加星球以及关系,并查集维护此时连通块个数

就是这个星球被打击前的答案

#include <cstdio>
#include <vector>
#include <iostream>
using namespace std;
#define maxn 400005
vector < int > h[maxn];
pair < int, int > p[maxn];
int n, m, k, ans;
int f[maxn], g[maxn], ret[maxn];
bool used[maxn], vis[maxn];void makeset() {for( int i = 0;i < n;i ++ ) f[i] = i;
}int find( int x ) {return x == f[x] ? x : f[x] = find( f[x] );
}void merge( int u, int v ) {u = find( u ), v = find( v );if( u ^ v ) ans --, f[v] = u;
}int main() {scanf( "%d %d", &n, &m );for( int i = 1;i <= m;i ++ ) {scanf( "%d %d", &p[i].first, &p[i].second );h[p[i].first].push_back( i );h[p[i].second].push_back( i );}scanf( "%d", &k );makeset();for( int i = 1;i <= k;i ++ )scanf( "%d", &g[i] ), used[g[i]] = 1;ans = n - k;for( int i = 1;i <= m;i ++ )if( ! used[p[i].first] and ! used[p[i].second] )merge( p[i].first, p[i].second );for( int i = k;i;i -- ) {ret[i] = ans;ans ++;used[g[i]] = 0;for( auto t : h[g[i]] )if( vis[t] ) continue;else if( used[p[t].first] or used[p[t].second] )continue;else merge( p[t].first, p[t].second );}printf( "%d\n", ans );for( int i = 1;i <= k;i ++ )printf( "%d\n", ret[i] );return 0;
}

In Touch

source

转化成最短路问题,套用dijkstra\rm dijkstradijkstra,每个点都只访问一次,但是范围那么大,用并查集帮助跳过已访问点,直指新点

#include <iostream>
#include <cstdio>
#include <queue>
using namespace std;
#define Pair pair < int, int >
#define int long long
#define maxn 200005
#define inf 1e15
priority_queue < Pair, vector < Pair >, greater < Pair > > q;
int T, n;
int dis[maxn], f[maxn], L[maxn], R[maxn], c[maxn];
int MS[2] = { -1, 1 };int find( int x ) {return x == f[x] ? x : f[x] = find( f[x] );
}signed main() {scanf( "%lld", &T );while( T -- ) {scanf( "%lld", &n );for( int i = 1;i <= n;i ++ ) scanf( "%lld", &L[i] );for( int i = 1;i <= n;i ++ ) scanf( "%lld", &R[i] );for( int i = 1;i <= n;i ++ ) scanf( "%lld", &c[i] );for( int i = 0;i <= n + 1;i ++ ) f[i] = i, dis[i] = inf;q.push( make_pair( dis[1] = c[1], 1 ) );while( ! q.empty() ) {int now = q.top().second; q.pop();for( int k = 0;k < 2;k ++ ) {int l = now + L[now] * MS[k];int r = now + R[now] * MS[k];if( l > r ) swap( l, r );l = min( l, n + 1 );l = max( l, 1ll );if( l > r ) continue;for( int nxt = l;;nxt ++ ) {nxt = find( nxt );if( nxt <= 0 || nxt > n || nxt > r ) break;if( dis[nxt] > dis[now] + c[nxt] ) {dis[nxt] = dis[now] + c[nxt];q.push( make_pair( dis[nxt], nxt ) );}f[find( nxt )] = find( nxt + 1 );}}}printf( "0" );for( int i = 2;i <= n;i ++ )if( dis[i] == inf ) printf( " -1" );else printf( " %lld", dis[i] - c[i] );printf( "\n" );}return 0;
}

方格染色

source

observation1: 只要确定了第一行和第一列,整张表格就被确定了

observation2: g1,1⨁gi,1⨁g1,j⨁gi,j=[imod2=0andjmod2=0]g_{1,1}\bigoplus g_{i,1}\bigoplus g_{1,j}\bigoplus g_{i,j}=[i\ \rm mod\ 2=0\ and\ j\ mod\ 2=0]g1,1gi,1g1,jgi,j=[i mod 2=0 and j mod 2=0]

可以通过枚举g1,1g_{1,1}g1,1的状态,通过已知的gi,jg_{i,j}gi,j来判断gi,1,g1,jg_{i,1},g_{1,j}gi,1,g1,j的关系

这样形成了若干组有且仅有两个选项的约束关系,带权并查集维护

连通块内有一个取值定了,其他的取值也定了

如果有解,答案就是2^(连通块数量-1),减1是g1,1g_{1,1}g1,1的状态因为是枚举的,算已知的

#include <cstdio>
#define int long long
#define mod 1000000000
#define maxn 2000005
int n, m, k;
bool flag0, flag1;
int x[maxn], y[maxn], c[maxn], f[maxn], w[maxn];int qkpow( int x, int y ) {int ans = 1;while( y ) {if( y & 1 ) ans = ans * x % mod;x = x * x % mod;y >>= 1;}return ans;
}int find( int x ) {if( x == f[x] ) return x;else {int fa = f[x];f[x] = find( f[x] );w[x] = ( w[x] + w[fa] ) % 2;return f[x];}
}int solve() {for( int i = 1;i <= n + m;i ++ ) f[i] = i, w[i] = 0;f[n + 1] = 1;for( int i = 1;i <= k;i ++ ) {if( x[i] == 1 && y[i] == 1 ) continue;int u = find( x[i] ), v = find( y[i] + n );int t = w[x[i]] ^ w[y[i] + n] ^ c[i] ^ ( x[i] & 1 or y[i] & 1 ) ^ 1;if( u == v and t ) return 0;f[v] = u, w[v] = t;} int cnt = 0;for( int i = 1;i <= n + m;i ++ )if( find( i ) == i ) cnt ++;return qkpow( 2, cnt - 1 );
}signed main() {scanf( "%lld %lld %lld", &n, &m, &k );for( int i = 1;i <= k;i ++ ) {scanf( "%lld %lld %lld", &x[i], &y[i], &c[i] );if( x[i] == 1 && y[i] == 1 )if( ! c[i] ) flag0 = 1;else flag1 = 1;else;}int ans0 = solve();//c[g[1][1]]=0 bluefor( int i = 1;i <= k;i ++ ) c[i] ^= 1;//c[g[1][1]]=1 redint ans1 = solve();if( flag0 ) ans1 = 0;if( flag1 ) ans0 = 0;printf( "%lld\n", ( ans0 + ans1 ) % mod );return 0;
}

Junk-Mail Filter

source

可删除并查集模板

只需要注意一下被删除前的集合若只有一个,元素被删除后集合也就不存在了

#include <cstdio>
#include <iostream>
using namespace std;
#define maxn 2200000
int n, m, ans, cnt;
int f[maxn], siz[maxn];void makeset() {cnt = n;for( int i = 0;i < n;i ++ )f[i] = f[i + n] = cnt ++, siz[i + n] = 1;
}int find( int x ) {return x == f[x] ? x : f[x] = find( f[x] );
}void merge( int u, int v ) {u = find( u ), v = find( v );if( siz[u] < siz[v] ) swap( u, v );if( u ^ v )siz[u] += siz[v], f[v] = u, ans --;
}void Delete( int x ) {int fx = find( x );siz[fx] --;if( ! siz[fx] ) ans --;f[x] = f[cnt] = cnt;siz[cnt] = 1;cnt ++;ans ++;
}int main() {int T = 0;while( scanf( "%d %d", &n, &m ) ) {if( ! n and ! m ) return 0;makeset();ans = n;char opt[5]; int x, y;for( int i = 1;i <= m;i ++ ) {scanf( "%s", opt );if( opt[0] == 'M' ) {scanf( "%d %d", &x, &y );merge( x, y );}else {scanf( "%d", &x );Delete( x );}}printf( "Case #%d: %d\n", ++ T, ans );}return 0;
}

[NOIP2010 提高组] 关押罪犯

source

贪心,先把冲突最大的安排,可以选择拆点i,i+ni,i+ni,i+n,两个人不同合并(i,j+n)/(i+n,j)(i,j+n)/(i+n,j)(i,j+n)/(i+n,j)

也可以选择带权并查集在%2\% 2%2意义下做

#include <cstdio>
#include <algorithm>
using namespace std;
#define maxn 100005
struct node {int u, v, w;node(){}node( int U, int V, int W ) {u = U, v = V, w = W;}
}r[maxn];
int n, m;
int f[maxn];void makeset() {for( int i = 1;i <= ( n << 1 );i ++ ) f[i] = i;
}int find( int x ) {return x == f[x] ? x : f[x] = find( f[x] );
}void merge( int u, int v ) {u = find( u ), v = find( v ), f[v] = u;
}int main() {scanf( "%d %d", &n, &m );for( int i = 1, u, v, w;i <= m;i ++ ) {scanf( "%d %d %d", &u, &v, &w );r[i] = node( u, v, w );}makeset();sort( r + 1, r + m + 1, []( node x, node y ) { return x.w > y.w; } );for( int i = 1;i <= m;i ++ ) {int u = r[i].u, v = r[i].v;if( find( u ) == find( v ) )return ! printf( "%d\n", r[i].w );elsemerge( u, v + n ), merge( v, u + n );}printf( "0\n" );return 0;
}

Silver Woods

source

跟一道奶酪题相似,奶酪是空心球,老鼠从底到顶;这道题是从左到右

二分半径,然后将圆卡不过的连接起来

具体而言就是点点之间距离小于直径,点和上下界面距离小于直径,合并起来

并查集判断上界面和下界面是否相通,不通证明有一种方法圆可以通过

#include <cstdio>
#include <cmath>
#define eps 1e-6
#define maxn 105
int n;
double x[maxn], y[maxn];
int f[maxn];void makeset() {for( int i = 0;i <= n + 1;i ++ ) f[i] = i;
}int find( int x ) {return x == f[x] ? x : f[x] = find( f[x] );
}void merge( int u, int v ) {u = find( u ), v = find( v ), f[v] = u;
}double dis( int i, int j ) {return sqrt( ( x[i] - x[j] ) * ( x[i] - x[j] ) + ( y[i] - y[j] ) * ( y[i] - y[j] ) );
}bool check( double r ) {double d = r * 2;makeset();for( int i = 1;i <= n;i ++ ) {if( y[i] + d >= 100 )merge( 0, i );if( y[i] - d <= -100 )merge( n + 1, i );for( int j = i + 1;j <= n;j ++ )if( dis( i, j ) < d )merge( i, j );}if( find( 0 ) == find( n + 1 ) ) return 0;else return 1;
}int main() {scanf( "%d", &n );for( int i = 1;i <= n;i ++ )scanf( "%lf %lf", &x[i], &y[i] );double l = 0, r = 100, ans;while( r - l > eps ) {double mid = ( l + r ) / 2;if( check( mid ) ) ans = mid, l = mid;else r = mid;}printf( "%.6f\n", ans );return 0;
}

Must Be Rectangular!

source

img

对于每个坐标(xi,yi)(xi,yi)(xi,yi)xixixiyi+nyi+nyi+n连边,形成一个二分图

然后后续添加点实际上就是对这个二分图的每个分量补成完全二分图

并查集维护一下二分图的边的个数,两个部的点的个数

#include <cstdio>
#define maxn 100000
int n;
int f[maxn << 2], row[maxn << 2], col[maxn << 2];void makeset() {for( int i = 1;i <= ( maxn << 1 );i ++ )f[i] = i;
}int find( int x ) {return x == f[x] ? x : f[x] = find( f[x] );
}void merge( int u, int v ) {u = find( u ), v = find( v ), f[v] = u;
}int main() {scanf( "%d", &n );makeset();for( int i = 1, x, y;i <= n;i ++ ) {scanf( "%d %d", &x, &y );merge( x, y + maxn );}long long ans = 0;for( int i = 1;i <= maxn;i ++ ) row[find( i )] ++;for( int i = 1;i <= maxn;i ++ ) col[find( i + maxn )] ++;for( int i = 1;i <= maxn;i ++ ) ans += 1ll * row[i] * col[i];printf( "%lld\n", ans - n );return 0;
}

{
u = find( u ), v = find( v ), f[v] = u;
}

int main() {
scanf( “%d”, &n );
makeset();
for( int i = 1, x, y;i <= n;i ++ ) {
scanf( “%d %d”, &x, &y );
merge( x, y + maxn );
}
long long ans = 0;
for( int i = 1;i <= maxn;i ++ ) row[find( i )] ++;
for( int i = 1;i <= maxn;i ++ ) col[find( i + maxn )] ++;
for( int i = 1;i <= maxn;i ++ ) ans += 1ll * row[i] * col[i];
printf( “%lld\n”, ans - n );
return 0;
}


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/317239.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JavaWeb --第二章 Tomact详情

JavaWeb --第二章 Tomact详情 文章目录Tomcat安装TomcatTomcat启动和配置配置发布一个web网站Tomcat 安装Tomcat 去官方下载 https://tomcat.apache.org Tomcat启动和配置 文件夹作用&#xff1a; 启动/关闭 Tomcat&#xff1a; 文件夹bin/startup.bat 开启 网址&#x…

开源的类似于Apache ab的压力测试命令行工具SuperBenchmarker

SuperBenchmarker 是ㄧ个开源的类似于Apache ab的压力测试命令行工具。可以在 .NET 4.52 或者 .NET Core 2.0 平台上运行。可支持Get、Post、Put、Delete这些调用方式&#xff0c;调用时能指定Concurrent user、Request数、Header template…等。可以从Github、Chocolatey这两种…

如何优雅的利用Windows服务来部署ASP.NET Core程序

上一篇文章中我给大家讲述了五种部署ASP.NET Core网站的方法&#xff0c;其中有一种方式是通过Windows服务来进行部署&#xff0c;这样既可以做到开启自启动&#xff0c;又不会因为iis的反向代理而损失部分性能。但是美中不足的是需要借助第三方软件nssm来进行&#xff0c;那么…

JavaWeb --第四章Maven详解

JavaWeb --第四章Maven详解 文章目录MavenMaven架构管理工具下载安装Maven配置环境变量阿里云镜像本地仓库在IDEA中使用Maven创建一个普通的Maven项目在IDEA中标记文件夹功能在IDEA中配置tomcatpom文件IDEA操作解决遇到的问题Maven 为什么要学这个技术&#xff1f; 在javaweb…

用StyleCop规范团队代码

前言编码风格&#xff0c;每个人都是有不同的特点&#xff0c;风格各异&#xff0c;而且一个人在不同的时期&#xff0c;编码风格的差异也可能是非常大的&#xff0c;好比学生时代&#xff0c;刚工作的时候&#xff0c;工作一段时间后等。在一个团队中&#xff0c;或一个项目中…

一键发布部署vs插件[AntDeploy],让net开发者更幸福

一键发布工具(ant deploy tool)插件下载地址&#xff1a;https://marketplace.visualstudio.com/items?itemNamenainaigu.AntDeploy1.iis一键发布自动部署 (iis deploy support)支持netcore 和 netframework发布 (支持mvc webapi)支持website自动创建ps:需要在windows 服务器上…

计算几何全家桶

文章目录前言精度点/向量相关表示向量基本运算角度相关向量夹角旋转直线/线段相关表示点与线求点到直线垂足求点关于直线的对称点点与直线的位置关系点与直线的距离线与线直线与直线的位置关系共线与垂直判断线段与线段是否相交求直线与直线的交点角平分线中垂线多边形表示求多…

什么是量子计算机?用一个简单例子来解释

译者&#xff1a;王亮 作者&#xff1a;YK Sugi 原文&#xff1a;http://t.cn/EZAElk0Hi&#xff0c;大家好&#xff01;不久前&#xff0c;我参观了加拿大温哥华的D-Wave Systems公司&#xff0c;这是一家制造前沿量子计算机的公司。我在那里学到了很多关于量子计算机的知识&a…

解决Azure DevOps部署到Azure后.NET Core网站无法启动的问题

点击上方蓝字关注“汪宇杰博客”最近我遭遇了一个奇怪的问题。使用Azure DevOps配置CI/CD管线&#xff0c;自动部署到Azure App Service以后&#xff0c;.NET Core的网站竟然会启动失败。我们来看看如何解决这个问题。查找问题首先&#xff0c;幸好&#xff0c;这是个staging环…

Acwing 135 最大子序和

Acwing 135 最大子序和 题目&#xff1a; 输入一个长度为 n 的整数序列&#xff0c;从中找出一段长度不超过 m 的连续子序列&#xff0c;使得子序列中所有数的和最大。 题解&#xff1a; 我们把这个问题的集合分成n份&#xff0c;第k份表示以A[k]结尾的最大连续子序列是多少…

.net core自定义高性能的Web API服务网关

网关对于服务起到一个统一控制处理的作用&#xff0c;也便于客户端更好的调用&#xff1b;通过网关可以灵活地控制服务应用接口负载&#xff0c;故障迁移&#xff0c;安全控制&#xff0c;监控跟踪和日志处理等。由于网关在性能和可靠性上都要求非常严格&#xff0c;所以针对业…

微软宣布 Visual Studio 2019 将于4月2日正式发布

微软于去年发布了 Visual Studio 2019 预览版。今天&#xff0c;该公司宣布 Visual Studio 2019 正式版将于4月2日发布。微软在公告中表示&#xff1a;“欢迎加入我们在4月2号当天举办的 VS 2019 线上发布活动&#xff0c;这是一款更加现代化、创新且实用的生产力工具”。据悉&…

DotNetty 实现 Modbus TCP 系列 (三) Codecs Handler

DotNetty 实现 Modbus TCP 系列 (一) 报文类DotNetty 实现 Modbus TCP 系列 (二) ModbusFunction 类图及继承举例DotNetty 作为一个半成品&#xff0c;我们不需要关注细节的实现&#xff0c;只需要关注自己的业务即可&#xff0c;所以最主要的就是处理 Codecs 和 Handler。所有…

Acwing -- 单调队列优化的DP问题

文章目录引入acwing154 滑动窗口应用135 最大子序和1088.旅行问题AcWing 1087. 修剪草坪28AcWing 1089. 烽火传递AcWing 1090. 绿色通道AcWing 1091. 理想的正方形引入 acwing154 滑动窗口 题目链接 题解 应用 闫氏最优化问题分析法 135 最大子序和 题目&#xff1a; 输入…

模板:半平面交(计算几何)

所谓半平面交&#xff0c;就是和“半平先生”当面交谈。顾名思义&#xff0c;这是一个源于日本的算法。 &#xff08;逃&#xff09; 前言 感觉应用很灵活的一个算法&#xff0c;一切有两个变量的线性规划问题都可以转化为半平面交。 有时可能要注意取等问题&#xff08;指射…

[小技巧]C#中如何为枚举类型添加描述方法

背景在我们的日常开发中&#xff0c;我们会经常使用枚举类型。有时我们只需要显示枚举的值或者枚举值对应名称&#xff0c; 但是在某些场景下&#xff0c;我们可能需要将枚举值显示为不同的字符串。例&#xff1a; 当前我们有如下枚举Level这个枚举有4个可选值B, N, G, VG。 现…

Loj#3320-「CCO 2020」旅行商问题

正题 题目链接:https://loj.ac/p/3320 题目大意 有一张nnn个点的无向完全图&#xff0c;每一条边是红色或者蓝色&#xff0c;对于每个点sss求从这个点出发的一条尽量短的经过所有点的路径。 1≤n≤20001\leq n\leq 20001≤n≤2000 解题思路 显然地猜测一下最短的长度肯定是n…

AcWing 1087. 修剪草坪28

AcWing 1087. 修剪草坪 题意: 有n个数&#xff0c;不能选超过连续的k个数&#xff0c;问所能选的最大值是多少&#xff1f; 题解&#xff1a; 我们首先分析dp过程&#xff1a; dp[i]表示选择完前i个数的最大值 sum[i]表示前i项和 对于第i个数&#xff0c;它有两个情况&#…

工业通信的开源项目 HslCommunication 介绍

前言&#xff1a;本项目的孵化说来也是机缘巧合的事&#xff0c;本人于13年大学毕业后去了一家大型的国企工作&#xff0c;慢慢的走上了工业软件&#xff0c;上位机软件开发的道路。于14年正式开发基于windows的软件&#xff0c;当时可选的技术栈就是MFC和C#的winform&#xff…

【地狱副本】数据结构之线段树Ⅲ——区间最值/赋值/修改/历史值操作(HDU5306,Tyvj 1518,【清华集训2015】V,HDU6315,HDU1828,POJ3162)

文章目录Gorgeous SequenceTyvj 1518 CPU监控【清华集训2015】VNaive OperationsPictureWalking RaceGorgeous Sequence HDU5306 操作 区间与xxx取min\rm minmin查询区间最大值查询区间和 比较暴力的线段树维护区间 Max : 区间最大值sub_max : 严格小于最大值的区间次大值…