POJ 3438 Kruskal + DP

Title

Portal POJ 3538 Domestic Networks

answer

Make the graph connected and construct a spanning tree. Otherwise, delete the longest edge on the ring in the graph to make the answer better. Minimize the edge weight of the spanning tree and construct the minimum spanning tree. At this time, ensure that the kth, k ∈ [1, N − 1] k,k\in[1,N-1] on the treek,k[1,N1 ] The largest edge is the smallest and unique.

Known minimum spanning tree edge set EEE , the problem is transformed into dividing the edge into two weights and each does not exceedq 5, q 6 q5, q6q5,The edge set of q 6 minimizes the cost. dp [i] [j] dp[i][j]d p [ i ] [ j ] stands for beforeiiSome of the edges in i are of type5 55. Is it possible to make the type5 5The sum of the edge weights of 5 isjjj . LetiiThe weight of i edge isds [i] ds[i]ds[i],则有 d p [ i ] [ j ] = d p [ i − 1 ] [ j ]   ∣   d p [ i − 1 ] [ j − d s [ i ] ] dp[i][j]=dp[i-1][j]\ |\ dp[i-1][j-ds[i]] dp[i][j]=dp[i1][j]  dp[i1][jd s [ i ] ] can be compressed into one-dimensionalDP DPD P , considering the need to record the index of the last edge taken, it is necessary to ensure thatDP DPEach weight in D P and only record the edge with the smallest index dp [j] = {dp [j − ds [i]] dp [j] = 0 & dp [j − ds [i]] = 1 dp [j ] otherwise dp[j]=\begin{cases}dp[j-ds[i]] & dp[j]=0\ \&\ dp[j-ds[i]]=1\\ dp[j] & otherwise\\ \end{cases}dp[j]={ dp[jds[i]]dp[j]dp[j]=0 & dp[jds[i]]=1otherwise

#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 1005, maxm = 10005, inf = 0x3f3f3f3f;
struct edge
{
    
    
    int x, y, z, k;
    bool operator<(const edge &b) const {
    
     return z < b.z; }
} es[maxm];
int N, M, P5, Q5, P6, Q6, pre[maxm];
int fa[maxn], sz[maxn], tot, sum, ds[maxn], id[maxn];
bool dp[maxm], vs[maxn];

int find(int x) {
    
     return fa[x] == x ? x : (fa[x] = find(fa[x])); }

void merge(int x, int y)
{
    
    
    if (sz[x] < sz[y])
        swap(x, y);
    fa[y] = x, sz[x] += sz[y];
}

void kruskal()
{
    
    
    for (int i = 1; i <= N; ++i)
        fa[i] = i, sz[i] = 1;
    sort(es + 1, es + M + 1);
    tot = sum = 0;
    for (int i = 1; i <= M; ++i)
    {
    
    
        int x = find(es[i].x), y = find(es[i].y);
        if (x == y)
            continue;
        ds[++tot] = es[i].z, id[tot] = es[i].k, sum += ds[tot];
        merge(x, y);
    }
}

int main()
{
    
    
    while (~scanf("%d%d", &N, &M))
    {
    
    
        for (int i = 1, x, y, z; i <= M; ++i)
            scanf("%d%d%d", &x, &y, &z), es[i] = edge{
    
    x, y, z, i};
        scanf("%d%d%d%d", &P5, &Q5, &P6, &Q6);
        kruskal();
        if (tot < N - 1 || sum > Q5 + Q6)
        {
    
    
            puts("Impossible");
            continue;
        }
        memset(dp, 0, sizeof(dp));
        dp[0] = 1;
        for (int i = 1; i <= tot; ++i)
            for (int j = Q5; j >= ds[i]; --j)
                if (!dp[j] && dp[j - ds[i]])
                    dp[j] = 1, pre[j] = i;
        int res = inf, p = -1;
        for (int i = 0, t; i <= Q5; ++i)
            if (dp[i] && sum - i <= Q6 && (t = P5 * i + P6 * (sum - i)) < res)
                res = t, p = i;
        if (res == inf)
        {
    
    
            puts("Impossible");
            continue;
        }
        memset(vs, 0, sizeof(vs));
        while (p > 0)
            vs[pre[p]] = 1, p -= ds[pre[p]];
        printf("%d\n", res);
        for (int i = 1; i <= tot; ++i)
            printf("%d %d\n", id[i], vs[i] ? 5 : 6);
    }
    return 0;
}

Guess you like

Origin blog.csdn.net/neweryyy/article/details/114554028