Ghostbusters(并查集,最小生成树)

Ghostbusters

时间限制: 1 Sec  内存限制: 128 MB
提交: 33  解决: 7
[提交] [状态] [讨论版] [命题人:admin]

题目描述

The Bureau of Approved Peripherals for Computers (BAPC) is designing a new standard for computer keyboards. With every new norm and regulation, hardware becomes obsolete easily, so they require your services to write ?rmware for them.
A computer keyboard is an array of M rows and N columns of buttons. Every button has an associated probability. Furthermore, every column and every row of buttons has an associated cable, and every pressed button connects their row cable with their column cable (and vice versa!). The keyboard detects key presses by “sampling”. It sends an electric signal through the ?rst row. This signal spreads to columns that are connected to it through pressed buttons
on that column and to rows connected to these columns through other pressed buttons and so on. Every row or column that is connected, possibly indirectly, to the original row via pressed buttons receives the signal. The ?rmware stores which columns have received the signal. This process is repeated for every row.
It is easy to identify what was pressed if only one key was pressed. In this case only one pair (row, column) will make contact. But keyboards allow to press more than one key at the same time and unfortunately some combinations of key presses are impossible to tell apart. 
This phenomenon is called “ghosting”. For example, in a 2 × 2 keyboard, all combinations of three or four presses are impossible to tell apart, since every pair (row, column) makes electric contact (maybe indirectly), as can be seen in Figure 3.

Figure 3: Four examples of connected wires in a keyboard. Bold lines of the same colour indicate wires that are connected via pressed buttons, which are depicted as red dots. The two sets of pressed buttons on the right cannot be distinguished from each other, since they connect the same rows and columns.
The BAPC wants to deal with the problem of ghosting by ?nding the most likely combination of pressed keys that could have produced a particular set of signals.

输入

The input consists of
? A line containing two integers, M the number of rows of the keyboard and N the number of columns, with 1 ≤ M, N ≤ 500. 
? M lines with N numbers each, where the jth number in the ith line indicates the probability 0 < p < 0.5 that the key in row i and column j is pressed. Here 0 ≤ i ≤ M ? 1 and 0 ≤ j ≤ N ? 1.
? M lines, each with an integer 0 ≤ k ≤ N and a list of k integers. The list of integers on the ith line indicates the columns that received the signal emitted by the ith row.

输出

Output the set of pressed keys that is most likely given the input. Any solution that achieves the maximum probability will be accepted. For each pressed key output a line with two integers r and c, separated by a space, indicating the row r and the column c of the key. The lines must be outputted in lexicographical order, that is, output ?rst the keys whose row is lower and if the rows are the same output ?rst the key whose column is lower.

样例输入

2 2
0.1 0.4
0.4 0.4
2 0 1
2 0 1

样例输出

0 1
1 0
1 1

思路:题意晦涩难懂,读明白就非常简单!

AC代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 struct UnionFind
 4 {
 5     vector<int> par,ra,si;
 6     int c;
 7     UnionFind(int n):par(n),ra(n,0),si(n,1),c(n)
 8     {
 9         for(int i=0;i<n;++i) par[i]=i;
10     }
11     int findd(int i)
12     {
13         return (par[i]==i?i:(par[i]=findd(par[i])));
14     }
15     bool same(int i,int j)
16     {
17         return findd(i)==findd(j);
18     }
19     int get_size(int i)
20     {
21         return si[findd(i)];
22     }
23     int countt()
24     {
25         return c;
26     }
27     void merg(int i, int j)
28     {
29         if((i=findd(i))==(j=findd(j))) return;
30         c--;
31         if(ra[i]>ra[j]) swap(i,j);
32         par[i]=j;
33         si[j]+=si[i];
34         if(ra[i]==ra[j]) ra[j]++;
35     }
36 };
37 struct prob
38 {
39     double p;
40     int r,c;
41 };
42 bool cmp(const prob &l, const prob &r)
43 {
44     return l.p>r.p;
45 }
46 bool super_cmp(const prob &l,const prob &r)
47 {
48     return tie(l.r,l.c)<tie(r.r,r.c);
49 }
50 int main()
51 {
52     int m,n;
53     scanf("%d %d",&m,&n);
54     vector<prob> ps;
55     ps.reserve(m*n);
56     for(int r=0;r<m;++r)
57     {
58         for(int c=0;c<n;++c)
59         {
60             prob p{0,r,c};
61             scanf("%lf",&p.p);
62             ps.push_back(p);
63         }
64     }
65     UnionFind target(m+n),cur(m+n);
66     for(int r=0;r<m;++r)
67     {
68         int k,c;
69         scanf("%d",&k);
70         while(k--) scanf("%d",&c),target.merg(r,m+c);
71     }
72     sort(ps.begin(),ps.end(),cmp);
73     vector<prob> ans;
74     for(auto &p:ps)
75     {
76         if(target.same(p.r,m+p.c) && !cur.same(p.r,m+p.c))
77         {
78             cur.merg(p.r,m+p.c),ans.push_back(p);
79         }
80     }
81     sort(ans.begin(),ans.end(),super_cmp);
82     for(auto &x:ans) printf("%d %d\n",x.r,x.c);
83     return 0;
84 }

原文地址:https://www.cnblogs.com/lglh/p/9594524.html

时间: 2024-08-30 14:25:36

Ghostbusters(并查集,最小生成树)的相关文章

ACM: 继续畅通工程-并查集-最小生成树-解题报告

继续畅通工程 Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Submit Status Description 省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可).现得到城镇道路统计表,表中列出了任意两城镇间修建道路的费用,以及该道路是否已经修通的状态.现请你编写程序,计算出全省畅通需要的最低成本. Input 测试输入包含若干测试用例

Kruskal算法(贪心+并查集=最小生成树)

http://www.51nod.com/ Kruskal算法的高效实现需要一种称作并查集的结构.我们在这里不介绍并查集,只介绍Kruskal算法的基本思想和证明,实现留在以后讨论. Kruskal算法的过程: (1) 将全部边按照权值由小到大排序. (2) 按顺序(边权由小到大的顺序)考虑每条边,只要这条边和我们已经选择的边不构成圈,就保留这条边,否则放弃这条边. 算法 成功选择(n-1)条边后,形成一个棵最小生成树,当然如果算法无法选择出(n-1)条边,则说明原图不连通. 以下图为例: 边排

hdu 1863 畅通工程 (并查集+最小生成树)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1863 畅通工程 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 17593    Accepted Submission(s): 7417 Problem Description 省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交

hdu 1272 小希的迷宫(并查集 最小生成树)

http://acm.hdu.edu.cn/showproblem.php?pid=1272 这题要求任意两个房间都相通又不能有环 即通过并查集求出是否构成最小生成树 #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define maxn 100000 int fa[maxn+10]; int num[maxn+10

CodeForces - 891C: Envy(可撤销的并查集&amp;最小生成树)

For a connected undirected weighted graph G, MST (minimum spanning tree) is a subgraph of G that contains all of G's vertices, is a tree, and sum of its edges is minimum possible. You are given a graph G. If you run a MST algorithm on graph it would

1863 畅通工程-并查集最小生成树

题目链接 问题描述: 简单的最小生成树的题,将路径按cost从小到大排序,利用克鲁斯塔尔求最小生成树算法就行. 代码: 1 #include<iostream> 2 #include<queue> 3 #include<algorithm> 4 5 using namespace std; 6 struct Road 7 { 8 int beg; 9 int end; 10 int cost; 11 Road(int beg, int end, int cost) 12

ACM : Travel-并查集-最小生成树 + 离线-解题报告

Travel Time Limit:1000MS     Memory Limit:131072KB     64bit IO Format:%I64d & %I64u /*题意 给出n[节点数],m[连线数],q[查询次数]; 输入m组数据 u[起点],v[终点],cost[权值]; (u,v)和 (v,u)表示两种不同的连线 输入q组查询数据: 要求 输出在m组数据中所有cost<q的所有节点连线的连线方式个数. 注意:每个拥有n个节点的联通块有 n*(n-1)个联通分量 (连线数):

Aizu-2224Save your cats并查集+最小生成树

Save your cats 题意:存在n个点,有m条边( input中读入的是 边的端点,要先转化为边的长度 ),做一个最小生成树,使得要去除的边的长度总和最小: 思路:利用并查集和求最小生成树的方法,注意这里的排序要从大到小排,这样最后建树的消耗最大,反过来去除的最小: 当然题意不是这么直白,感觉以后看到要做一个不成环的图时,要想到最小生成树: 下面是ac代码: #include <cstdio> #include <iostream> #include <cstring

hdu1863 畅通工程 并查集+最小生成树

Problem Description 省政府"畅通工程"的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可).经过调查评估,得到的统计表中列出了有可能建设公路的若干条道路的成本.现请你编写程序,计算出全省畅通需要的最低成本. Input 测试输入包含若干测试用例.每个测试用例的第1行给出评估的道路条数 N.村庄数目M ( < 100 ):随后的 N 行对应村庄间道路的成本,每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间

hdu 1879 继续畅通工程 (并查集+最小生成树)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1879 继续畅通工程 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 14075    Accepted Submission(s): 6136 Problem Description 省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公