【发布时间】:2019-04-04 14:47:07
【问题描述】:
我在Smith Set、Schwartz Set、Kosaraju's Algorithm、Tarjan's Algorithm 和path-based strongly component algorithms 上阅读过维基百科;但是,我对此类算法的经验……缺乏。维基百科还说您可以使用 Kosaraju 算法的版本来生成 Schwartz 集,并且这些算法可以计算 Smith 集。
维基百科也有一些 Tarjan 算法的伪代码,但没有其他的;它并不特定于这个相对敏感的应用程序。我也不是 100% 确定哪个是最容易实现的——哪个具有实现中出错可能性最小的特性。
我想要一些更直接的伪代码来涵盖从其中一种算法计算 Smith 和 Schwartz 集,给定一组排名选票。当我有一个可以行走的实际过程时,我发现更容易掌握概念。我会自己把它变成实际的代码。
考虑以下数据结构:
Type Ballot {
Array Votes[] {
Candidate Candidate; // We do this in C#
int Rank;
}
}
对于选票集合,每个单独的选票将包含一个数组 Votes,如下所示:
Ballot b.Votes[] =
[ Vote(Alex.ID, 1),
Vote(Chris.ID, 3),
Vote(Sam.ID, 2) ];
这对应于投票Alex>Sam>Chris 的选民,并且可能还有其他候选人都比克里斯更不受欢迎。
我认为第一步是统计个人选票并绘制胜利图。例如:如果 100 位选民将 Alex 排在 Sam 之上(Alex = 1,Sam >= 2),并且 50 位选民将 Sam 排在 Alex 之上,则 Alex 击败 Sam。因此我猜会有这样的数据结构:
Type GraphNode {
Candidate Candidate;
GraphNode Array Defeats[];
GraphNode Array Ties[];
GraphNode Array DefeatedBy[];
}
因此,Alex 的 GraphNode 将在 Defeats[] 中有一个元素指向 Sam 的 GraphNode,反之亦然。
鉴于这些 GraphNodes,我如何用它来识别 Smith 和 Schwartz 集?
提前致谢。
【问题讨论】:
-
这必须有多高效?维基百科的文章还列出了 Floyd-Warshall 算法,该算法会更慢但更容易实现。
-
如果它的时间复杂度相同,那很好。图形的最大大小很可能永远只有 9,因此重复重新计算任一集合的上限将是 7 次运行。很可能这些算法中的任何一种都很好,即使是 O(n^3) 算法。
-
有了这么小的图,你甚至可以尝试所有的子集,只有 2^9 = 512 种可能性。仍然 O(n^3) Floyd-Warshall 方法可能更容易。
-
我不确定我是否了解 Floyd-Warshall 如何适用。它确定了最短路径,但我正在研究强连接的组件。如果 A 击败 B,B 击败 C,C 击败 A,并且 {A,B,C} 中的每一个都击败了所有 {D,E,F,G},则史密斯集是 {A,B,C}。我相信如果 C 只与 A联系,史密斯集是 {A,B,C},施瓦茨集是 {A}。
标签: algorithm pseudocode voting