📌  相关文章
📜  移除给定 Q 个顶点后给定图中的连通分量计数

📅  最后修改于: 2022-05-13 01:58:11.034000             🧑  作者: Mango

移除给定 Q 个顶点后给定图中的连通分量计数

给定一个无向图g ,任务是找出在所有这些连通分量中去除Q个顶点和最大顶点后在其中形成的联盟数。

联盟定义为移除Q个顶点后留下的连通分量的数量,即从图中移除的顶点不被视为联盟的一部分。

例子:

方法:基于以下思想解决此问题的方法

基于上述想法,请按照以下步骤实施此方法:

  1. 我们可以使用 multimap 来存储顶点之间的边。
  2. 我们删除所有与顶点连接的边(因为我们假设我们必须从查询中删除所有顶点,因此它们对应的边也应该与顶点连接)
  3. 求无向图中连通分量的个数。
    • 使用变量count来存储连接组件的数量,使用cnt来记录我们正在遍历的组件的顶点数,并使用 maxLen来存储所有组件中的最大顶点( cnt的最大值)。
  4. 计算联盟=计数(连接组件的数量)-查询的大小(删除的顶点数)

下面是上述方法的实现:

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的数组。