acwing 3725. Structural complete map (pressure dp)

Posted by stueee on Wed, 19 Jan 2022 23:05:41 +0100

1. Topic introduction

Third question of Game 6 of acwing week Title portal
An undirected connected graph consisting of n points and m edges is given.

We want to turn it into a complete graph through a series of operations (that is, each pair of different vertices has exactly one edge connected).

During each operation, you can select one of the points, find all the points directly connected to it, and connect the edges between these points (if there are already edges between the two points, there is no need to connect them repeatedly).

How many operations can you change the whole graph into a complete graph?

Input format
The first line contains two integers n,m.

The next m lines contain two integers u and V, indicating that there is an edge between point u and point v.

All points are numbered 1 ∼ n.

Output format
The first line outputs the minimum number of operations.

The second line outputs the number of points selected for each operation, separated by spaces between integers. If the minimum number of operations is 0, the second line does not need to be output.

If the answer is not unique, any reasonable scheme can be output.

Data range
The first three test points meet 1 ≤ N and m ≤ 10.
All test points meet 1 ≤ n ≤ 22, 0 ≤ m ≤ n(n − 1) 2, 1 ≤ u,v ≤ n, u ≠ v.
Ensure that there are no double edges and self rings, and ensure that the given graph is connected.

Input example 1:
5 6
1 2
1 3
2 3
2 5
3 4
4 5
Output example 1:
2
2 3
Input example 2:
4 4
1 2
1 3
1 4
3 4
Output example 2:
1
1
Difficulty: difficulty
Time / space limit: 2s / 256MB
Total number of passes: 110
Total attempts: 322
Source: AcWing, week 6
Algorithm label

2. Problem solving ideas

2.1 look before solving the problem. The maximum data range n is 22. The data is not large. There are many algorithms that can be used. According to the difficulty of the problem and y total Complexity and algorithm content of inverse calculation method from data range It can be concluded that either search or pressure dp.
2.2 read through the topic. Given n points and m edges, you can select one point at a time and connect all the points connected with it. It is required to find the minimum number of steps and all the selected points that constitute a complete graph.
2.3 assuming that the algorithm to be used in this problem is search, there are two schemes to connect the points that have not been passed each time. In a word, search is to construct a 1-N Full Permutation, plus all the possibilities of each point selection and non selection. The total time complexity is (n! * 2 ^ n). If 22 is substituted, it is much larger than 1e8, so the search cannot be performed.
2.4 assuming that the algorithm to be used for this problem is state pressure dp, which is feasible from the data, then analyze the feasibility. The first step of state pressure dp is to list n selected and unselected States S (2^n),
Step 2 select a point contained in the current state from the current state S and connect it with all the edges it can connect to to obtain a new state T. judge whether S - > t is better (the number of steps is smaller). If it is better, update and record it.
From the perspective of algorithm, it is feasible to enumerate all States (2^n) in terms of time complexity. Each state enumerates all points O(n) it contains in turn, and the total time complexity (n * 2^n). If it is substituted into 22, it is about 1e8, and the given time is 2 seconds. It is completely ok, which is feasible.

code implementation

#include<bits/stdc++.h>
#define x first
#define y second
using namespace std;

typedef pair<int, int> P;
const int N = 22, M = 1 << 22, inf = 1e9 + 7;

int n, m, u, v;
int e[N];//Record all points that can be connected to each point
int f[M];//State array, which records the minimum cost of reaching each state
P g[M];// Tag array, the subscript is the current state, fist records the state before reaching the current state, and second records the point drilled by the current arrival shape

int main()
{
    cin >> n >> m;
     if (m == n * (n - 1) / 2) //Special judgment: n = 1, m = 0
    {
        puts("0\n");
        return 0;
    }

    memset(f, inf, sizeof f);//The cost of initialization reaching all States is infinite
    for (int i = 0; i < n; ++i) e[i] = 1 << i; //Record yourself to yourself
    for (int i = 0; i < m; ++i) {//Record all points that can be reached by the input points
        cin >> u >> v;
        u--; v--;
        e[u] |= 1 << v;
        e[v] |= 1 << u;
    }
    //                         Record the status after connecting from the current point once
    for (int i = 0; i < n; ++i) f[e[i]] = 1, g[e[i]] = {0, i};
    for (int S = 0; S < 1 << n; ++S) { //Enumerate all States
        if (f[S] == inf) continue; 
        for (int j = 0; j < n; ++j) {
            if (S >> j & 1) { // There are j points in the current state
                if (f[S | e[j]] > f[S] + 1) { // From current state S to S | e[j]
                    f[S | e[j]] = f[S] + 1;
                    g[S | e[j]] = {S, j}; 
                }
            }
        }
    }
    int k = (1 << n) - 1; // Finally, the state in which all points are included
    cout << f[k] << endl; 
    while (k) { // Output path
        cout << g[k].y + 1 << ' ';
        k = g[k].x;
    }
    return 0;
}