移除给定 Q 个顶点后给定图中的连通分量计数
给定一个无向图g ,任务是找出在所有这些连通分量中去除Q个顶点和最大顶点后在其中形成的联盟数。
联盟定义为移除Q个顶点后留下的连通分量的数量,即从图中移除的顶点不被视为联盟的一部分。
例子:
Input: V = 7, E = 6, Q = 1
Edges: { {0, 3}, {1, 5}, {3, 6}, {3, 2}, {2, 4}, {5, 6} }
queries: {3}
Output: 3 3
Explanation:
If we remove vertices 3 from the graph then their corresponding edges {{0, 3}, {3, 6}, {3, 2}} will also be get removed from the graph and the number of the connected components excluding Q (removed vertices) are {0}. {1, 5, 6} and {2, 4} with maximum coalition of {1, 5, 6} as 3.
Input: V = 6, E = 6, Q = 2
Edges: {{0, 3}, {0, 2}, {3, 4}, {3, 5}, {3, 1}, {2, 4}}
queries: {1, 2}
Output: 1 4
Explanation: When vertex 1 and 2 is removed from the given graph the connected component excluding Q is {0, 3, 4, 5} with maximum coalition of {0, 3, 4, 5} as 4.
方法:基于以下思想解决此问题的方法
The idea here is, if we remove all unnecessary edges that connects with the vertex mentioned in the query, then the problem will break down to find the number of connected component in undirected graph.
基于上述想法,请按照以下步骤实施此方法:
- 我们可以使用 multimap 来存储顶点之间的边。
- 我们删除所有与顶点连接的边(因为我们假设我们必须从查询中删除所有顶点,因此它们对应的边也应该与顶点连接)
- 求无向图中连通分量的个数。
- 使用变量count来存储连接组件的数量,使用cnt来记录我们正在遍历的组件的顶点数,并使用 maxLen来存储所有组件中的最大顶点( cnt的最大值)。
- 计算联盟=计数(连接组件的数量)-查询的大小(删除的顶点数)
下面是上述方法的实现:
C++14
#include
using namespace std;
int maxLen = 0;
int cnt;
class Graph {
int V;
list* adj;
multimap adj2;
void DFSUtil(int v, bool visited[]);
public:
Graph(int V);
void addEdges();
void removeEdges(int V, int Edges[][2],
int E, int queries[],
int Q);
int NumberOfconnectedComponents();
};
// function to find the number of connected
// component in undirected graph
int Graph::NumberOfconnectedComponents()
{
bool* visited = new bool[V];
int count = 0;
for (int v = 0; v < V; v++)
visited[v] = false;
for (int v = 0; v < V; v++) {
if (visited[v] == false) {
cnt = 0;
DFSUtil(v, visited);
count += 1;
}
}
return count;
}
void Graph::DFSUtil(int v, bool visited[])
{
visited[v] = true;
cnt++;
list::iterator i;
for (i = adj[v].begin(); i != adj[v].end(); ++i)
if (!visited[*i]) {
DFSUtil(*i, visited);
}
maxLen = max(maxLen, cnt);
}
Graph::Graph(int V)
{
this->V = V;
adj = new list[V];
}
// add Edges in the graph
void Graph::addEdges()
{
for (auto x : adj2) {
adj[x.first].push_back(x.second);
adj[x.second].push_back(x.first);
}
}
// function to remove all the edges that are
// connected with vertices
void Graph::removeEdges(int V, int Edges[][2],
int E, int queries[],
int Q)
{
multimap adj3;
for (int i = 0; i < E; i++)
adj3.insert({ Edges[i][0], Edges[i][1] });
for (int i = 0; i < Q; i++) {
auto it1 = adj3.lower_bound(queries[i]);
auto it2 = adj3.upper_bound(queries[i]);
adj3.erase(it1, it2);
}
for (auto it = adj3.begin(); it != adj3.end(); it++) {
adj2.insert({ it->second, it->first });
}
for (int i = 0; i < Q; i++) {
auto it1 = adj2.lower_bound(queries[i]);
auto it2 = adj2.upper_bound(queries[i]);
adj2.erase(it1, it2);
}
}
// Driver code
int main()
{
int V = 7, E = 6;
Graph g(V);
int Edges[][2] = { { 0, 3 }, { 1, 5 }, { 3, 6 }, { 3, 2 }, { 2, 4 }, { 5, 6 } };
int Q = 1;
int queries[] = { 3 };
// remove all the edges that are connected with
// vertices given in the queries
g.removeEdges(V, Edges, E, queries, Q);
g.addEdges();
cout << g.NumberOfconnectedComponents() - Q;
cout << " " << maxLen;
return 0;
}
3 3
时间复杂度: O(V + E*log(E)),其中V是顶点数, E是图中的边数。
辅助空间: O(V),因为需要一个额外访问的大小为V的数组。