写在前面
- 实现思路
- Dijkstra计算最短路径
- DFS递归迭代计算最优解
- 变量、函数相对较繁琐,涉及知识点较多
研究ing
- 不会告诉你,
一般博主不太懂的问题,都不怎么总结
测试用例
input:
10 3 3 5
6 7 0
0 1 1
0 2 1
0 3 3
1 3 1
2 3 1
output:
3 0->2->3 0
ac代码
#include
#include
#include
#include
using namespace std;
const int maxv = 510;
const int inf = 1000000;
int n,m,cmax,sp,numPath=0, G[maxv][maxv], weight[maxv];
int d[maxv], minNeed = inf, minRemain = inf;
bool vis[maxv] = {false};
vector<int> pre[maxv];
vector<int> tmpPath, path;
void Dijkstra(int s)
{
fill(d, d+maxv, inf);
d[s] = 0;
for(int i=0; i<n; i++)
{
int u=-1, mins = inf;
for(int j=0; j<=n; j++)
{
if(vis[j] == false && d[j]<mins)
{
u = j;
mins = d[j];
}
}
if(u==-1) return;
vis[u] = true;
for(int v=0; v<=n; v++)
{
if(vis[v] == false && G[u][v] != inf)
{
if(d[u] +G[u][v] < d[v])
{
d[v] = d[u] + G[u][v];
pre[v].clear();
pre[v].push_back(u);
}
else if(d[u] + G[u][v]==d[v]) pre[v].push_back(u);
}
}
}
}
void DFS(int v)
{
if(v==0)
{
tmpPath.push_back(v);
int need = 0, remain = 0;
for(int i=tmpPath.size()-1; i>=0; i--)
{
int id = tmpPath[i];
if(weight[id]>0)
remain += weight[id];
else
{
if(remain > abs(weight[id])) remain -= abs(weight[id]);
else
{
need += abs(weight[id])-remain;
remain = 0;
}
}
}
if(need < minNeed)
{
minNeed = need;
minRemain = remain;
path = tmpPath;
}
else if(need == minNeed && remain < minRemain)
{
minRemain = remain;
path = tmpPath;
}
tmpPath.pop_back();
return;
}
tmpPath.push_back(v);
for(int i=0; i<pre[v].size(); i++) DFS(pre[v][i]);
tmpPath.pop_back();
}
int main()
{
scanf("%d%d%d%d", &cmax,&n,&sp,&m);
int u, v;
fill(G[0], G[0]+maxv*maxv, inf);
for(int i=1; i<=n; i++)
{
scanf("%d", &weight[i]);
weight[i] -= cmax/2;
}
for(int i=0; i<m; i++)
{
scanf("%d%d", &u, &v);
scanf("%d", &G[u][v]);
G[v][u] = G[u][v];
}
Dijkstra(0);
DFS(sp);
printf("%d ", minNeed);
for(int i=path.size()-1; i>=0; i--)
{
printf("%d", path[i]);
if(i>0) printf("->");
}
printf(" %d", minRemain);
return 0;
}
学习代码
#include
#include
#include
using namespace std;
const int inf = 99999999;
int cmax, n, sp, m;
int minNeed = inf, minBack = inf;
int e[510][510], dis[510], weight[510];
bool visit[510];
vector<int> pre[510], path, temppath;
void dfs(int v) {
temppath.push_back(v);
if(v == 0) {
int need = 0, back = 0;
for(int i = temppath.size() - 1; i >= 0; i--) {
int id = temppath[i];
if(weight[id] > 0) {
back += weight[id];
} else {
if(back > (0 - weight[id])) {
back += weight[id];
} else {
need += ((0 - weight[id]) - back);
back = 0;
}
}
}
if(need < minNeed) {
minNeed = need;
minBack = back;
path = temppath;
} else if(need == minNeed && back < minBack) {
minBack = back;
path = temppath;
}
temppath.pop_back();
return ;
}
for(int i = 0; i < pre[v].size(); i++)
dfs(pre[v][i]);
temppath.pop_back();
}
int main() {
fill(e[0], e[0] + 510 * 510, inf);
fill(dis, dis + 510, inf);
scanf("%d%d%d%d", &cmax, &n, &sp, &m);
for(int i = 1; i <= n; i++) {
scanf("%d", &weight[i]);
weight[i] = weight[i] - cmax / 2;
}
for(int i = 0; i < m; i++) {
int a, b;
scanf("%d%d", &a, &b);
scanf("%d", &e[a][b]);
e[b][a] = e[a][b];
}
dis[0] = 0;
for(int i = 0; i <= n; i++) {
int u = -1, minn = inf;
for(int j = 0; j <= n; j++) {
if(visit[j] == false && dis[j] < minn) {
u = j;
minn = dis[j];
}
}
if(u == -1) break;
visit[u] = true;
for(int v = 0; v <= n; v++) {
if(visit[v] == false && e[u][v] != inf) {
if(dis[v] > dis[u] + e[u][v]) {
dis[v] = dis[u] + e[u][v];
pre[v].clear();
pre[v].push_back(u);
}else if(dis[v] == dis[u] + e[u][v]) {
pre[v].push_back(u);
}
}
}
}
dfs(sp);
printf("%d 0", minNeed);
for(int i = path.size() - 2; i >= 0; i--)
printf("->%d", path[i]);
printf(" %d", minBack);
return 0;
}
知识点小结
- 技能待更新
- tips
- fill函数:将一个区间的元素都赋予val值
- 函数参数:fill(vec.begin(), vec.end(), val); val为待替换的值
- 代码示例
# include
fill(vec.begin(), vec.end(), val);
int a[10];
fill(a, a+10, 20);