admin管理员组

文章数量:1558087

题目链接:点击打开链接

思路:

选一些边, 使得任意两点都可以相互到达且花费最小,  这显然是最小生成树, 将边挑选出来之后, 如果贪心选取的话, 有可能导致无解, 所以我们考虑用动态规划。

根据数据量, 用d[i][j]表示前i个边, 第一种颜料用了j单位长度下的最小花费,  因为没条边都选, 那么用总和减去j就是第二种颜料的花费。  用path[i][j]表示改状态下从哪一个状态转移过来的,  注意到第一维不需要记录, 只记录第二维就行了。

细节参见代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <stack>
#include <ctime>
#include <bitset>
#include <cstdlib>
#include <cmath>
#include <set>
#include <list>
#include <deque>
#include <map>
#include <queue>
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;
typedef long long ll;
typedef long double ld;
const double eps = 1e-6;
const double PI = acos(-1);
const int mod = 1000000000 + 7;
const int INF = 0x3f3f3f3f;
// & 0x7FFFFFFF
const int seed = 131;
const ll INF64 = ll(1e18);
const int maxn = 10000 + 10;
int T,n,m,p[1010],d[1010][maxn],sum[1010];
short path[1010][maxn];
struct node {
    int a, b, c, id;
    node(int a=0, int b=0, int c=0, int id=0):a(a), b(b), c(c), id(id) {}
    bool operator < (const node& rhs) const {
        return c < rhs.c;
    }
}e[maxn];
int _find(int x) { return p[x] == x ? x : p[x] = _find(p[x]); }
struct Edge {
    int a, b, c, id;
    Edge(int a=0, int b=0, int c=0, int id=0):a(a), b(b), c(c), id(id) {}
    bool operator < (const Edge& rhs) const {
        return id > rhs.id;
    }
} edge[maxn];
int main() {
    while(~scanf("%d%d", &n, &m)) {
        for(int i = 1; i <= m; i++) {
            scanf("%d%d%d", &e[i].a, &e[i].b, &e[i].c);
            e[i].id = i;
        }
        sort(e+1, e+m+1);
        int cnt = 0;
        for(int i = 0; i <= n; i++) p[i] = i;
        for(int i = 1; i <= m; i++) {
            int x = _find(e[i].a);
            int y = _find(e[i].b);
            if(x != y) {
                p[x] = y;
                edge[++cnt] = Edge(e[i].a,e[i].b,e[i].c,e[i].id);
            }
        }
        int p5, p6, q5, q6;
        scanf("%d%d%d%d", &p5, &q5, &p6, &q6);
        if(cnt != n-1) {
            printf("Impossible\n");
            continue;
        }
        sort(edge+1, edge+cnt+1);
        for(int i = 1; i <= cnt; i++) sum[i] = sum[i-1] + edge[i].c;
        memset(d, 0x3f, sizeof(d));
        d[0][0] = 0;
        for(int i = 1; i <= cnt; i++) {
            for(int j = 0; j <= q5; j++) {
                if(sum[i]-j >= edge[i].c && sum[i]-j <= q6 && d[i-1][j] != INF) {
                    if(d[i][j] > d[i-1][j] + edge[i].c*p6) {
                        d[i][j] = d[i-1][j] + edge[i].c*p6;
                        path[i][j] = j;
                    }
                }
                if(j >= edge[i].c && d[i-1][j-edge[i].c] != INF) {
                    if(d[i][j] > d[i-1][j-edge[i].c] + edge[i].c*p5) {
                        d[i][j] = d[i-1][j-edge[i].c] + edge[i].c*p5;
                        path[i][j] = j-edge[i].c;
                    }
                }
            }
        }
        int ans = INF, pos = 0;
        for(int i = 0; i <= q5; i++) {
            if(ans > d[cnt][i]) {
                ans = d[cnt][i];
                pos = i;
            }
        }
        if(ans == INF) {
            printf("Impossible\n");
            continue;
        }
        int res = cnt;
        printf("%d\n", ans);
        while(res > 0) {
            printf("%d ", edge[res].id);
            if(pos == path[res][pos]) printf("6\n");
            else printf("5\n");
            pos = path[res][pos];
            res--;
        }
    }
    return 0;
}


本文标签: POJDomesticDPNetworks