题目地址
1.dijkstra找最短路
2.pre[i]维护到其他节点到i节点花费最小的节点,即存下所有最短路的路径。
3.dfs遍历所有最短路,维护minback和minneed.
#include<bits/stdc++.h>
using namespace std;
const int inf = 0x3f3f3f3f;
int grape[505][505],dis[505],weight[505];
vector<int > pre[505],path,temppath;
int cmax,n,sp,t,minneed=inf,minback=inf;
bool vis[505];
void dfs(int u)
{
temppath.push_back(u);
if(u==0)
{
int back=0,need=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[u].size();i++)
{
dfs(pre[u][i]);
}
temppath.pop_back();
}
int main()
{
//二维数组用fill要grape[0]开始
fill(grape[0],grape[0]+505*505,inf);
fill(dis,dis+505,inf);
scanf("%d%d%d%d",&cmax,&n,&sp,&t);
for(int i=1;i<=n;i++)
{
scanf("%d",&weight[i]);
weight[i] = weight[i] - cmax/2;
}
for(int i=1;i<=t;i++)
{
int u,v,val;
scanf("%d%d%d",&u,&v,&val);
grape[u][v] = val;
grape[v][u] = val;
}
dis[0] = 0;
for(int i=0;i<=n;i++)
{
int u = -1,mins = inf;
for(int j=0;j<=n;j++)
{
if(vis[j]==false&&dis[j]<mins)
{
u = j;
mins = dis[j];
}
}
//所有节点都访问过后跳出
if(u == -1) break;
vis[u] = true;
for(int v = 0 ; v <= n; v ++)
{
if(vis[v]==false&&grape[u][v]!=inf)
{
//vis[v] = true;这里的v不是访问到的节点!!!
if(dis[v] > dis[u] + grape[u][v])
{
dis[v] = dis[u] + grape[u][v];
//pre存储到达V点花费最少的节点
pre[v].clear();
pre[v].push_back(u);
}
else
{
if(dis[v]==dis[u] + grape[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;
}