Steiner tree summary

Steiner tree

There isn't a lot of information on this thing online

Definition of a virgin

Steiner tree problem is a combinatorial optimization problem, which is similar to minimum spanning tree and is a type of shortest network.
The minimum spanning tree is to find the shortest network in a given set of points and edges to connect all points.
Whereas a minimal Steiner tree allows additional points to be added beyond a given point, resulting in the shortest network with minimal overhead.

I personally think that this thing should be a certain type of minimum spanning tree problem without a polynomial solution, and then it can be solved by the shape pressure DP

Start directly with a topic

 

 

[WC2008] Tour Plan

Link

This should be a board question for Steiner trees.

We let $f[i][sta]$ represent the node of $i$, and the connectivity with other nodes is the minimum cost of $sta$, where $sta$ is a binary number, under its binary In the bit, $0$ indicates disconnection, $1$ indicates connection

Then there are two situations when transferring

  • transferred from subset

方程为$$f[i][sta] = \min_{s \in sta}\{f[i][s] + f[i][\complement_ssta] - val[i]\}$$

The latter reduction is to prevent aggravation

Here's a trick when enumerating subsets

 for(int s = sta; s; s = (s - 1) & sta) 

This enumerates all subsets of sta

  • Transferred from the state that does not contain the node

 The transfer equation is

where $i$ is the newly added node

$$f[i][j] = \min\{f[k][j] + val[i]\}$$

Do you have a very familiar feeling when you see this equation?

Does it look like a triangle inequality?

So we can do this transfer with SPFA

 

full code

// luogu-judger-enable-o2
// luogu-judger-enable-o2
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
const int limit = 1050;
const int INF = 1e9;
inline int read() {
    char c = getchar(); int x = 0, f = 1;
    while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
    while(c >= '0' && c <= '9') {x = x * 10 + c - '0'; c = getchar();}
    return x *f;
}
#define MP(i,j) make_pair(i,j)
#define se second
#define fi first
#define Pair pair<int,int>
int N, M, tot = 0;
int a[12][12], f[12][12][limit];
int xx[5] = {-1, +1, 0, 0};
int yy[5] = {0, 0, -1, +1};
int vis[12][12];
struct PRE {
    int x, y, S;
}Pre[12][12][limit];
queue<Pair>q;
void SPFA(int cur) {
    while(q.size() != 0) {
        Pair p = q.front();q.pop();
        vis[p.fi][p.se] = 0;
        for(int i = 0; i <4; i++) {
            int wx = p.fi + xx[i], wy = p.se + yy[i];
            if(wx < 1 || wx > N || wy < 1 || wy > M) continue;
            if(f[wx][wy][cur] > f[p.fi][p.se][cur] + a[wx][wy]) {
                f[wx][wy][cur] = f[p.fi][p.se][cur] + a[wx][wy];
                Pre[wx][wy][cur] = (PRE){p.fi, p.se, cur};
                if(!vis[wx][wy])
                    vis[wx][wy] = 1, q.push(MP(wx,wy));
            }
        }
    }
}
void dfs(int x, int y, int now) {
    vis[x][y] = 1 ;
    PRE tmp = Pre[x][y][now];
    if(tmp.x == 0 && tmp.y == 0) return;
    dfs(tmp.x, tmp.y, tmp.S);
    if(tmp.x == x && tmp.y == y) dfs(tmp.x, tmp.y, now - tmp.S);
}
int main() {
    //freopen("a.in", "r", stdin);
    N = read(); M = read();
    memset(f, 0x3f, sizeof(f));
    for(int i = 1; i <= N; i++)
        for(int j = 1; j <= M; j++) {
            a[i][j] = read();
            if(a[i][j] == 0)
                f [i] [j] [ 1 << all] = 0 , all ++ ;
        }
    int limit = (1 << tot) - 1;
    for(int sta = 0; sta <= limit; sta++) {
        for(int i = 1; i<= N; i++)
            for(int j = 1; j <= M;j++) {
                for(int s = sta; s; s = (s - 1) & sta) {
                    if(f[i][j][s] + f[i][j][sta - s] - a[i][j] < f[i][j][sta])
                        f[i][j][sta] = f[i][j][s] + f[i][j][sta - s] - a[i][j],
                        Pre [i] [j] [sta] = (PRE) {i, j, s};
                }
                if(f[i][j][sta] < INF) q.push(MP(i,j)), vis[i][j] = 1;
            }
        SPFA (sta);
    }
    int ansx, ansy, flag = 0;
    for(int i = 1; i <= N && !flag; i++)
        for(int j = 1; j <= M; j++)
            if(!a[i][j]) 
                {ansx = i, ansy = j; flag = 1; break;}
    printf("%d\n",f[ansx][ansy][limit]); 
    memset(vis, 0, sizeof(vis));
    dfs (ansx, ansy, limit);
    for(int i = 1; i <= N; i++, puts("")) {
        for(int j = 1; j <= M; j++) {
            if(a[i][j] == 0) putchar('x');
            else if(vis[i][j]) putchar('o');
            else putchar('_');            
        }
    }
    return 0;
}

 

 

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325101278&siteId=291194637