想查看其他题的真题及题解的同学可以前往查看:CCF-CSP真题附题解大全
试题编号: | 202305-4 |
试题名称: | 电力网络 |
时间限制: | 1.0s |
内存限制: | 512.0MB |
问题描述: | 问题描述西西艾弗岛电力公司需要修建一套电网对岛上的众多城镇进行供电。电网设施包括建造在城镇中的变电站,与建造在城镇间的输电线路。根据前期的考察结果,电力公司已经确定了哪些城镇之间需要建造输电线路,以使得所有城镇能够被连接成一个电力网络。每座城镇只需要建造一个变电站,却都向电力公司提供了多个建造候选地址。对于每个城镇,不同候选地址的变电站造价不同;对于城镇间的输电线路,其造价也会随着两端变电站的候选地址的变化而变化。因此,电力公司想要知道,在所有候选地址的组合中,电网的总造价(变电站造价加上输电线路造价)最低是多少。 输入格式从标准输入读入数据。 输入的第一行包括三个正整数 N、M、K。表示一共有 N 座城镇,需要建造 M 条输电线路,每座城镇都提供了 K 个变电站候选地址。 接下来输入 N 行,每行表示一个城镇。每行包含 K 个整数,表示该城镇不同候选地址的变电站造价。 接下来 M 行,每行表示一条输电线路,包含 K2+2 个整数。前两个整数表示该输电线路两端的城镇,范围是 [0, N)。第三个整数开始是大小为 K×K 的矩阵 T 的行主序存储形式。Tij 表示当输电线路的第一个端点选择候选地址 i,第二个端点选择候选地址 j 时的线路造价。 输出格式输出到标准输出中。 输出包含一行,这一行有一个整数,表示电网的最低总造价。 样例输入 Data 样例输出 Data 样例说明城镇 0 与城镇 1 均选择了 0 号地址建造变电站。 子任务对于全部数据,保证由城镇与输电线路构成的图是无向无重边无自环的连通图,保证单个变电站与单条线路的造价均不超过 1000。 对于 20% 的数据,保证 N≤6,K≤10。 对于另外 20% 的数据,保证 N≤104,K≤10,M=N−1。 对于另外 20% 的数据,保证 N≤104,K≤10,M=N。 对于另外 20% 的数据,保证 N≤104,K≤10。图中存在两个节点 S、D,保证全图去除 D 节点和与 D 节点相连的边后,可以构成以 S 节点为根的一棵树,而且所有与 D 相连的节点都属于这棵树的叶子节点。 对于最后 20% 的数据,保证 N≤104,K≤10,且度数大于 2 的节点数量 ≤6。 |
真题来源:电力网络
感兴趣的同学可以如此编码进去进行练习提交
c++ 80分题解:
#include
using namespace std;
using LL = long long;
const LL inf = 1e18;
int main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int n, k, m;
cin >> n >> m >> k;
vector> pcost(n, vector(k));
for(auto &i : pcost)
for(auto &j : i)
cin >> j;
vector>> edge(n);
vector> edges(m);
vector> ecost(m, vector(k * k));
for(int i = 0; i < m; ++ i){
int u, v;
cin >> u >> v;
edges[i] = {u, v};
edge[u].push_back({v, i});
edge[v].push_back({u, i});
for(auto &j : ecost[i])
cin >> j;
}
if (n <= 6 && k <= 10){
vector used(n);
LL ans = inf;
LL tmp = 0;
function dfs = [&](int x){
if (x == n){
LL back = tmp;
for(int i = 0; i < m; ++ i){
int u = edges[i][0], v = edges[i][1], id = i;
int r = used[u] * k + used[v];
tmp += ecost[id][r];
}
ans = min(ans, tmp);
tmp = back;
return;
}
for(int i = 0; i < k; ++ i){
tmp += pcost[x][i];
used[x] = i;
dfs(x + 1);
tmp -= pcost[x][i];
}
};
dfs(0);
cout << ans << '\n';
}else if (m == n - 1){
vector> dp(n, vector(k, 0));
function dfs = [&](int u, int fa){
for(auto e : edge[u]){
int v = e[0], id = e[1];
if (v == fa)
continue;
dfs(v, u);
for(int i = 0; i < k; ++ i){
LL tmp = inf;
for(int j = 0; j < k; ++ j){
int L = i, R = j;
if (u != edges[id][0])
swap(L, R);
int r = L * k + R;
tmp = min(tmp, dp[v][j] + pcost[v][j] + ecost[id][r]);
}
dp[u][i] += tmp;
}
}
};
dfs(0, 0);
LL ans = inf;
for(int i = 0; i < k; ++ i)
ans = min(ans, dp[0][i] + pcost[0][i]);
cout << ans << '\n';
}else if (m == n){
vector id(n);
iota(id.begin(), id.end(), 0);
int ignore = 0;
function findfa = [&](int x){
return x == id[x] ? x : id[x] = findfa(id[x]);
};
for(int i = 0; i < m; ++ i){
int u = edges[i][0], v = edges[i][1];
int fu = findfa(u), fv = findfa(v);
if (fu == fv){
ignore = i;
break;
}
id[fu] = fv;
}
vector> dp(n, vector(k, 0));
LL ans = inf;
int fixed = edges[ignore][0], st = edges[ignore][1];
for(int col = 0; col < k; ++ col){
for(auto &i : dp)
fill(i.begin(), i.end(), 0);
function dfs = [&](int u, int fa){
for(auto e : edge[u]){
int v = e[0], id = e[1];
if (v == fa || id == ignore)
continue;
dfs(v, u);
for(int i = 0; i < k; ++ i){
if (u == fixed && i != col)
continue;
LL tmp = inf;
for(int j = 0; j < k; ++ j){
if (v == fixed && j != col)
continue;
int L = i, R = j;
if (u != edges[id][0])
swap(L, R);
int r = L * k + R;
tmp = min(tmp, dp[v][j] + pcost[v][j] + ecost[id][r]);
}
dp[u][i] += tmp;
}
}
};
dfs(st, st);
for(int i = 0; i < k; ++ i){
int L = i, R = col;
if (st != edges[ignore][0])
swap(L, R);
int r = L * k + R;
ans = min(ans, dp[st][i] + pcost[st][i] + ecost[ignore][r]);
}
}
cout << ans << '\n';
}else{
vector du(n);
for(int i = 0; i < m; ++ i){
int u = edges[i][0], v = edges[i][1];
++ du[u];
++ du[v];
}
int target = 0;
for(int i = 0; i < n; ++ i){
if (m - du[i] == n - 2){
target = i;
break;
}
}
vector forbid(n, 0);
for(auto &e : edge[target]){
int v = e[0];
forbid[v] = 1;
}
int st = 0;
while(st == target || forbid[st])
++ st;
vector> dp(n, vector(k, 0));
LL ans = inf;
for(int col = 0; col < k; ++ col){
for(auto &i : dp)
fill(i.begin(), i.end(), 0);
function dfs = [&](int u, int fa){
for(auto e : edge[u]){
int v = e[0], id = e[1];
if (v == fa)
continue;
if (v != target)
dfs(v, u);
for(int i = 0; i < k; ++ i){
LL tmp = inf;
for(int j = 0; j < k; ++ j){
if (v == target && j != col)
continue;
int L = i, R = j;
if (u != edges[id][0])
swap(L, R);
int r = L * k + R;
if (v == target){
tmp = min(tmp, 1ll * ecost[id][r]);
}else{
tmp = min(tmp, dp[v][j] + pcost[v][j] + ecost[id][r]);
}
}
dp[u][i] += tmp;
}
}
};
dfs(st, st);
for(int i = 0; i < k; ++ i){
ans = min(ans, dp[st][i] + pcost[st][i] + pcost[target][col]);
}
}
cout << ans << '\n';
}
return 0;
}
运行结果: