A : Wireless Network  POJ - 2236

题意:并查集,可以有查询和修复操作

题解:并查集

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
#define N 1110
int d;
bool use[N]; struct node
{
int pre;
int x, y;
}p[N]; int find(int x)
{
return x == p[x].pre ? x : find(p[x].pre);
} void join(const node p1, const node p2)
{
int root1, root2;
root1 = find(p1.pre);
root2 = find(p2.pre);
if(root1 != root2)
if((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y) <= d * d)
p[root2].pre = root1;
} int main()
{
//freopen("Input.txt", "r", stdin);
int num;
char ope;
int ok;
int from, to;
scanf("%d%d", &num, &d);
for(int i = ; i <= num; ++i)
p[i].pre = i;
memset(use, false, sizeof(use));
for(int i = ; i <= num; ++i)
scanf("%d%d", &p[i].x, &p[i].y);
while(scanf("\n%c", &ope) != EOF)
{
if(ope == 'O')
{
scanf("%d", &ok);
use[ok] = true;
for(int i = ; i <= num; ++i)
if(use[i] && i != ok)
join(p[i], p[ok]);
}
else
{
scanf("%d%d", &from, &to);
if(find(from) == find(to))
printf("SUCCESS\n");
else
printf("FAIL\n");
}
}
return ;
}

B:The Suspects POJ - 1611

题意:0节点为携带病毒人,有一些团队,一个人可以在多个团队,一个团队一个有病毒,其余都感染,问一共几人感染病毒

题解:寻找0号根结点对应的sum值

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<sstream>
#include<cmath>
#include<stack>
#include<cstdlib>
#include <vector>
#include<queue>
using namespace std; #define ll long long
#define llu unsigned long long
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
const int maxn = 1e5+;
const int mod = 1e9+; int father[maxn],sum[maxn];
void init(int n)
{
for(int i=;i<n;i++)
{
father[i] = i;
sum[i] = ;
}
}
int find(int x)
{
if(father[x] == x)
return x;
else
return father[x] = find(father[x]);
}
void combine(int x,int y)
{
int xx = find(x);
int yy = find(y);
if(xx != yy) {
father[xx] = yy;
sum[yy] += sum[xx];
}
}
int main()
{
int n,m;
while(~scanf("%d %d",&n,&m))
{
init(n);
if(n == && m == )
break;
for(int i=;i<m;i++)
{
int x;
scanf("%d",&x);
int one,two;
scanf("%d",&one);
for(int j=;j<x;j++)
{
scanf("%d",&two);
combine(one,two);
}
}
printf("%d\n",sum[find()]);
}
}

C:How Many Tables  hdu-1213

题意:认识的人可以坐在一张桌子,也可以间接认识,问需要几张桌子

思路:并查集之后找有几个集

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<sstream>
#include<cmath>
#include<stack>
#include<map>
#include<cstdlib>
#include <vector>
#include<queue>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 1e3+; int father[maxn];
void init(int n)
{
for(int i=;i<=n;i++)
father[i] = i;
}
int find(int x)
{
if(father[x] == x)
return x;
else
return father[x] = find(father[x]);
}
void combine(int x,int y)
{
x = find(x);
y = find(y);
if(x != y)
father[x] = y;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n,m;
scanf("%d %d", &n,&m);
init(n);
for(int i=;i<m;i++)
{
int a,b;
scanf("%d%d",&a,&b);
combine(a,b);
}
int res = ;
for(int i=;i<=n;i++)
if(i == find(i))
res++;
printf("%d\n",res);
}
}

D:How Many Answers Are Wrong  hdu-3038

题意:现在有n个数(你并不知道这n个数是什么),m次查询,每次查询给出u,v,w。表示从第u个数到第v个数的和为w。
   问,在这些查询中,有多少个是错误的(即有冲突)。

思路:带权并查集

从第u个数到第v个数的和其实可以理解为,第u-1个数到v个数之间的和。那么,就可以把和当成一种关系,利用带权并查集来维护这种关系。u-1节点为根,v的权值为第u-1个数到v个数之间的和。这里需要理解一下的是,在Find函数和unite(合并)函数里面,有两个关系域的转移方程(暂且这么叫他吧)
①p[x].relation+=p[tmp].relation
②p[root2].relation=p[x].relation+relation-p[y].relation

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<sstream>
#include<cmath>
#include<stack>
#include<map>
#include<cstdlib>
#include <vector>
#include<queue>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 2e5+;
struct node
{
int father;
int w;
};
node p[maxn];
int n,m,ans;
void init()
{
ans = ;
for(int i=;i<=n;i++)
{
p[i].father = i;
p[i].w = ;
}
} int find(int x)
{
if(x == p[x].father)
return x;
int tmp = p[x].father;
p[x].father = find(tmp);
p[x].w += p[tmp].w;
return p[x].father;
} void combine(int x,int y,int w)
{
int x1 = find(x);
int y1 = find(y);
if(x1 != y1)
{
p[y1].father = x1;
p[y1].w = p[x].w + w -p[y].w;
}
else
{
if(p[y].w - p[x].w != w)
ans ++;
}
} int main()
{
while(~scanf("%d %d",&n,&m))
{
int u,v,w;
init();
for(int i=;i<m;i++)
{
scanf("%d %d %d",&u,&v,&w);
u -= ;
combine(u,v,w);
}
printf("%d\n",ans);
}
}

E - 食物链 POJ - 1182

题意:A吃B,B吃C,C吃A,给出一些话,问有几句假话

题解:可开3倍数组,也可以用结构体,关系域用向量加减操作

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<sstream>
#include<cmath>
#include<stack>
#include<map>
#include<cstdlib>
#include<vector>
#include<string>
#include<queue>
using namespace std; #define ll long long
#define llu unsigned long long
#define INF 0x3f3f3f3f
const double PI = acos(-1.0);
const int maxn = 5e4+;
const int mod = 1e9+; struct node
{
int pre;
int relation; //0:与根节点同类 1:被根节点吃 2:吃根节点
}p[maxn]; int find(int x)
{
int temp;
if(x == p[x].pre)
return x;
temp = p[x].pre;
p[x].pre = find(temp);
p[x].relation = (p[x].relation + p[temp].relation) % ;
return p[x].pre;
}
int main()
{
int n,k;
int ope,a,b;
int root1,root2;
int sum = ;
scanf("%d%d",&n,&k);
for(int i=;i<=n;i++)
{
p[i].pre = i;
p[i].relation = ;
}
while(k--)
{
scanf("%d%d%d",&ope,&a,&b);
if(max(a,b) > n)
{
sum++;
continue;
}
if(ope == && a == b)
{
sum++;
continue;
}
root1 = find(a);
root2 = find(b);
if(root1 != root2)
{
p[root2].pre = root1;
p[root2].relation = (+(ope - ) + p[a].relation - p[b].relation) % ;
}
else
{
if(ope == &&p[a].relation != p[b].relation)
{
sum++;
continue;
}
if(ope == &&(( - p[a].relation + p[b].relation) % != ope -))
{
sum++;
continue;
}
}
}
printf("%d\n",sum);
}

F - True Liars POJ - 1417

题目大意:给你p1个好人和p2个坏人,编号为1-p1+p2,然后给你n中操作

x1 x2 no:x1说x2不是好人

x1 x2 yes:x1说x2是好人

在这里好人说的总是对的,坏人说的总是坏的,然后问你最后能不能唯一确定哪些是好人,并输出不能就输出no

题目思路:开始看到这题很好想到的就是用并查集,如果是yes的话说明他们同类,no的话说明不是同类,但这样只能分出几个大集合来,每个集合又分成两个小集合表示两种类型的个数,而我们要求的是在所有大集合中选出一个小集合然后加起来看能不能组 合成p1,并且要唯一,这里我们可以想到用背包来做,dp[i][j]表示前i个大集合好人为j个的方案数,第i种状态只能是有第i-1种状态而来,我们用w0[i],w1[i]表示第i个集合两个小集合的个数 ,所以dp[i][j]可以由dp[i-1][j-w0[]i]和dp[i-1][j-w1[i]]得来,这样我们只需判断dp[cnt][p1]是否等于1,这题还有麻烦的就是输出好人的编号,这里我们可以利用边的权值,w0存的全是权值为0的w1存的全是权值为1的,然后最后只需判断下第i个集合是由w0还是w1组合而来,这里可以利用dp[i-1][p1-w0[i]]的值来判断,如果等于1则表示是由w0组合否则就是w1,这个不难理,dp[i-1][p1-w0[i]]==1可以得到dp[i][p1]==1,应为这里已经表示答案唯一,所以只有一种情况!

此题题意题解转载自:  https://blog.csdn.net/qq_34731703/article/details/54603652

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<sstream>
#include<cmath>
#include<stack>
#include<cstdlib>
#include <vector>
#include <set>
#include<queue>
using namespace std; #define ll long long
#define llu unsigned long long
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
const int maxn = 1e3+;
const ll mod = 1e9+; int pre[maxn],rk[maxn],p[maxn],vis[maxn];
int w0[maxn],w1[maxn],dp[maxn][maxn];
int n,p1,p2;
void init()
{
for(int i=;i<=p1+p2;i++)
{
pre[i] = i;
rk[i] = ;
vis[i] = ;
w0[i] = w1[i] = ;
}
memset(dp,,sizeof dp);
}
int find(int x)
{
if(x != pre[x])
{
int temp = pre[x];
pre[x] = find(pre[x]);
rk[x] = rk[x] ^ rk[temp];
}
return pre[x];
}
void combine(int x,int y,int k)
{
int xx = find(x);
int yy = find(y);
if(xx != yy)
{
pre[xx] = yy;
rk[xx] = rk[x] ^ rk[y] ^ k;
}
}
int main()
{
while(scanf("%d %d %d",&n,&p1,&p2) && (n + p1 + p2))
{
init();
for(int i=;i<n;i++)
{
int a,b;
char str[];
scanf("%d %d %s",&a,&b,str);
if(str[] == 'y')
combine(a,b,);
else
combine(a,b,);
}
int cnt = ;
for(int i=;i<=p1+p2;i++)
{
if(!vis[i])
{
int fa = find(i);
for(int j=i;j<=p1+p2;j++)
{
if(find(j) == fa && !vis[j])
{
vis[j] = ;
if(rk[j] == )
w0[cnt]++;
else
w1[cnt]++;
}
}
p[cnt] = fa;
cnt++;
}
}
dp[][] = ;
for(int i=;i<cnt;i++)
{
int minn = min(w0[i],w1[i]);
for(int j=p1;j>=minn;j--)
{
if(dp[i-][j-w0[i]])
dp[i][j] += dp[i-][j-w0[i]];
if(dp[i-][j-w1[i]])
dp[i][j] += dp[i-][j-w1[i]];
}
} if(dp[cnt-][p1] != )
{
puts("no");
continue;
}
int ans[maxn];
int num = ;
int good = p1;
for(int i=cnt-;i>=;i--)
{
if(dp[i-][good-w0[i]] == )
{
for(int j=;j<=p1+p2;j++)
if(find(j) == p[i] && rk[j] == )
ans[num++]=j;
good -= w0[i];
}
else
{
for(int j=;j<=p1+p2;j++)
if(find(j) == p[i] && rk[j] == )
ans[num++] = j;
good -= w1[i];
}
}
sort(ans,ans + num);
for(int i=;i<num;i++)
printf("%d\n",ans[i]);
puts("end");
}
return ;
}

G - Supermarket POJ - 1456

题意:超市里有n个产品要卖,每个产品都有一个截至时间d(从开始卖时算起),只有在这个截至时间之前才能卖出并且获得率润dy。

题解:先将产品按照价格从高到低排序,之后用并查集来寻找还有的时间

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<sstream>
#include<cmath>
#include<stack>
#include<cstdlib>
#include <vector>
#include <set>
#include<queue>
using namespace std; #define ll long long
#define llu unsigned long long
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
const int maxn = 1e4+;
const ll mod = 1e9+;
struct node
{
int p,d;
}a[maxn];
int pre[maxn];
bool cmp(node a,node b)
{
return a.p > b.p;
}
int find(int x)
{
if(pre[x] == -)
return x;
else
return pre[x] = find(pre[x]);
}
int main()
{
int n;
while(~scanf("%d",&n))
{
memset(pre,-,sizeof pre);
for (int i = ; i < n; i++)
scanf("%d %d",&a[i].p,&a[i].d);
sort(a,a+n,cmp);
int ans = ;
for(int i=;i<n;i++)
{
int t = find(a[i].d);
// cout<<t<<endl;
if(t)
{
ans += a[i].p;
pre[t] = t-;
//cout<<"pre[t]"<<t-1<<endl;
}
}
printf("%d\n",ans);
}
return ;
}

M - 小希的迷宫 HDU - 1272

题意:给一张地图,要求任意的两个房间之间只有一条路,是的输出Yes,不是的输出No

思路:使用并查集,当发现两个房间的根节点不一样的话就将两个房间连接起来,如果两个房间的根节点是一样的话,说明成环了,就不是。同时,也有可能不是联通的,需要验证,就是只有一个根节点在所有的点中,还有一个特判,直接输入0 0 的话输出的是Yes

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<sstream>
#include<cmath>
#include<stack>
#include<cstdlib>
#include <vector>
#include <set>
#include<queue>
#include<map>
using namespace std; #define ll long long
#define llu unsigned long long
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
const int maxn = 1e5+;
const ll mod = 1e9+;
const double eps = 1e-; int pre[maxn];
int vis[maxn]; void init()
{
for(int i=;i<maxn;i++)
pre[i] = i;
memset(vis,,sizeof vis);
}
int find(int x)
{
if(x == pre[x])
return x;
else
return pre[x] = find(pre[x]);
} void combine(int x,int y)
{
int fx = find(x);
int fy = find(y);
if(fx != fy)
pre[fy] = fx;
}
bool same(int x,int y)
{
int fx = find(x);
int fy = find(y);
return fx == fy;
}
int main()
{
int a,b;
while(scanf("%d%d",&a,&b))
{
init();
vis[a] = vis[b] = ;
if(a == - && b == -)
break;
if(a== && b==)
{
puts("Yes");
continue;
}
combine(a,b);
int x,y;
int flag = ;
while(scanf("%d%d",&x,&y))
{
if(x== && y==)
{
int ans = ;
for(int i=;i<maxn;i++)
if(vis[i] && pre[i]==i) {
ans++;
//cout<<i<<endl;
}
if(flag == && ans == )
puts("Yes");
else
puts("No");
break;
}
vis[x] = vis[y] = ;
if(!same(x,y))
combine(x,y);
else
flag = ;
}
}
}

kuangbin 并查集的更多相关文章

  1. [ An Ac a Day ^_^ ] [kuangbin带你飞]专题五 并查集 POJ 2236 Wireless Network

    题意: 一次地震震坏了所有网点 现在开始修复它们 有N个点 距离为d的网点可以进行通信 O p   代表p点已经修复 S p q 代表询问p q之间是否能够通信 思路: 基础并查集 每次修复一个点重新 ...

  2. kuangbin带你飞 并查集 题解

    做这套题之前一直以为并查集是很简单的数据结构. 做了才发现自己理解太不深刻.只看重片面的合并集合.. 重要的时发现每个集合的点与这个根的关系,这个关系可以做太多事情了. 题解: POJ 2236 Wi ...

  3. [kuangbin带你飞]专题五 并查集

    并查集的介绍可以看下https://www.cnblogs.com/jkzr/p/10290488.html A - Wireless Network POJ - 2236 An earthquake ...

  4. kuangbin带我飞QAQ 并查集

    1. POJ 2236 给出N个点,一开始图是空白的,两个操作,一个是增加一个点(给出坐标),一个是查询两个点间是否相通,当两点间的距离小于D或者两点通过其他点间接相连时说这两个点相通.并查集维护,每 ...

  5. POJ 1417 True Liars(种类并查集+dp背包问题)

    题目大意: 一共有p1+p2个人,分成两组,一组p1,一组p2.给出N个条件,格式如下: x y yes表示x和y分到同一组,即同是好人或者同是坏人. x y no表示x和y分到不同组,一个为好人,一 ...

  6. HDU 4750 Count The Pairs (2013南京网络赛1003题,并查集)

    Count The Pairs Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others ...

  7. poj2513连接木棍(字典树+欧拉回路+并查集)

    题目传送门 题目大意:给你一堆木棍,每根木管都有两种颜色,相同颜色的部分可以连接起来,问你这堆木棍可不可以连接成1根. 思路:大致的思路很好想,就是判断欧拉回路的方法(1.联通,2,要么顶点读书全为偶 ...

  8. POJ-2153Colored Sticks解题报告+欧拉回路,字典树,并查集;

    传送门:http://poj.org/problem?id=2513 题意:给你许多木棍,木棍两端都有颜色,问能不能首尾相接,要求颜色相同. 参考:https://www.cnblogs.com/ku ...

  9. BZOJ 4199: [Noi2015]品酒大会 [后缀数组 带权并查集]

    4199: [Noi2015]品酒大会 UOJ:http://uoj.ac/problem/131 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品 ...

随机推荐

  1. 关于Mdi窗口-父窗口上的控件把子窗口的挡住的问题

    using System.Runtime.InteropServices; [DllImport("user32")] public static extern int SetPa ...

  2. Python开发环境Wing IDE搜索工具介绍

    Wing IDE编辑器的搜索工具提供了一个基于友好GUI的搜索和替换工具. 某些情况下搜索可能会跨越整个文件,也有可能被限制到当前所选择的区域:可以区分大小写,也可以设置为不区分:可以被限制为只匹配整 ...

  3. Struct2标签的传值方式(转载)

    "#request.userList"> "center"> "id"/> : "username"/ ...

  4. sk-learning(2)

    sk-learning 学习(2) sklearing 训练评估 针对kdd99数据集使用逻辑回归分类训练 然后进行评估 发觉分数有点高的离谱 取出10%数据494021条,并从中选择四分之一作为测试 ...

  5. JIRA Plugin Development——Configurable Custom Field Plugin

    关于JIRA Plugin开发的中文资料相当少,这可能还是由于JIRA Plugin开发在国内比较小众的原因吧,下面介绍下自己的一个JIRA Plugin开发的详细过程. 业务需求 创建JIRA IS ...

  6. 详解Unity 4.6新UI的布局

    本文所讲的是Unity 4.6中新加入的uGUI,官方称Unity UI,而不是过去的OnGUI式的旧UI(官方称Legacy GUI). 我曾经在8月份对照4.6 Beta的文档写过一篇笔记学习Un ...

  7. mysqlimport命令

    mysqlimport的大多数选项直接对应LOAD DATA INFILE子句. 选项: -u,--user 指定连接用户名.   -p,--password[name] 指定连接用户的密码.   - ...

  8. Linux基础精华(转)

    Linux基础精华 (继续跟新中...) 常用命令: Linux shell 环境 让你提升命令行效 率的 Bash 快捷键 [完整版] 设置你自己的liux alias Linux的Find使用 L ...

  9. 启动tomcat的Cannot find ./catalina.sh 的问题

    从终端进入tomcat的bin目录,然后执行startup.sh Cannot find bin/catalina.sh The file is absent or does not have exe ...

  10. Deep Learning 优化方法总结

    Stochastic Gradient Descent (SGD) SGD的参数 在使用随机梯度下降(SGD)的学习方法时,一般来说有以下几个可供调节的参数: Learning Rate 学习率 We ...