https://ac.nowcoder.com/acm/contest/884/J
卡了2个小时的题 其实也不是很难 大家都做出来了 我们好菜
题意 给一个无向图 给出S T两个点 要从S走到T 最多删去K条边 问最短的权值之和
具体想法看代码吧 用迪杰斯特拉跑最短路 里面改一点 我又是抄的咖啡鸡的神仙代码 真的写的太美了
#include<algorithm>
#include<iostream>
#include<vector>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<string>
#include<ctime>
#include<map>
#include<stack>
#include<set>
#include<cstring>
#include<sstream>
#include<queue>
using namespace std;
typedef long long ll;
typedef pair<int, int> pi;
const int maxn = 1e3 + 5;
int n, m, S, T, k, dis[maxn][maxn];//dis是从s到i点免费j条边的权值
vector<pi> h[maxn];//边
struct node {
int u, s, dis;//u是dis[i] s是i
bool operator<(const node& u) const {
return dis > u.dis;
}
};
priority_queue<node> q;//优先队列q 优化时间复杂度
int main() {
cin >> n >> m >> S >> T >> k;
while (m--) {
int u, v, w;
cin >> u >> v >> w;
h[u].push_back(pi{ v, w });//建图
h[v].push_back(pi{ u, w });//建图
}
memset(dis, -1, sizeof(dis));//初始化为1
dis[S][0] = 0;//初始化起始点
q.push(node{ S,0,0 });//入队
while (!q.empty()) {
node tmp = q.top();//取出权值最小的
q.pop();
int u = tmp.u;//起始点
int s = tmp.s;//已经免费的边数
for (auto e : h[u]) {//遍历该起始点所有连到边
int v = e.first;//该边的终点
if (dis[v][s] == -1 || dis[v][s] >= dis[u][s] + e.second) {//起始点到v点没有线或者起始点到v的距离大于起始点到u点再到v点的距离 松弛操作
dis[v][s] = dis[u][s] + e.second;//更新
q.push(node{ v,s,dis[v][s] });//入队列
}
if (s == k) continue;//如果免费的边数用完了
if (dis[v][s + 1] == -1 || dis[v][s + 1] > dis[u][s]) {//起始点到v 大于起始点到u 直接省略了v和s之间的那段距离
dis[v][s + 1] = dis[u][s];//处理免费边部分
q.push(node{ v,s + 1,dis[v][s + 1] });
}
}
}
int ans = 1e9;
for (int i = 0; i <= k; i++) {//遍历 S -> T 之间省几条边最便宜
if (dis[T][i] != -1) {
ans = min(ans, dis[T][i]);
}
}
cout << ans << endl;
return 0;
}







Comments | NOTHING