The problem is NP-hard, so I will present an exponential solution. This solution has many points of improvement, some of which I will highlight.
The main idea is that each partition of vertices is connected by some edges. By trying all possible sets of edges and counting the number of sets for each partition, you can find the best possible partition (optimal solution).
In your previous approach, there was no domain to expand the search. To solve this, we used Disjoint Sets for partition representation and Power Sets to find all possible sets of edges.
public Partition Solve(Graph g, int min)
{
int max = 0;
Partition best;
foreach(var S in PowerSet(g.Edges))
{
var partition = BuildPartition(S);
if (IsInvalid(partition, min))
continue;
if (max >= partition.Length)
continue;
max = partition.Length;
best = partition;
}
return best;
}
public Partition BuildPartition(Graph g, IEnumerable<Edge> edges)
{
var partition = new DisjointSet(g.Vertexes);
foreach (var edge in edges)
{
if (partition.Find(edge.V1) == partition.Find(edge.V2))
continue;
partition.Union(edge.V1, edge.V2);
}
return parition;
}
public bool IsInvalid(Partition p, int min)
{
return p.Sets.Any(t => t.Sum(v => v.Weight) < min);
}
您可以在以下几个方面改进解决方案:
- 在PowerSet和IsInvalid条件中添加并行性
- 找到更好的方法来生成有效的边集
- 对于比最小值更重的顶点,有一些起始情况(始终会在单独的子图中)
算法的顺序由Power Set给出。
- Power Set:在这种情况下,对于N个顶点的图,最坏情况下将有3N-6条边,因此时间复杂度为O(2^N)。 - 建立分区:V + E * LogV,因此时间复杂度为O(NLogN)
- IsInvalid:O(V)
最后,Solve是O(2^N * N * LogN)
使用这个公式计算操作次数
希望这能帮到您!