算法是用Dijkstra+DFS的算法求解,通过Dijkstra算法求出所有的最短路径,然后再用DFS求出所有最短路径中的所要带的车辆最少和带回的车辆最少的路径。
首先定义所需要的变量:
int loadw[505][505];//边权
int nodew[505];//点权
int loadsumw[505];//边权和
vector<int>pre[505];//前置点
vector<int>temppath,path;//暂时路径与最终路径
int minremian,minneed;//最小携带和最小剩余
int vis[505];
初始化和读入数据
scanf("%d%d%d%d",&cmax,&n,&sp,&m);
nodew[0] = 0;
n++;
for(int i = 1;i<n;i++)
{
scanf("%d",&nodew[i]);
nodew[i] = nodew[i]-(cmax/2);
}
for(int i = 0;i<n;i++)
for(int j =0;j<n;j++)
loadw[i][j] = INF;
//cout<<1;
for(int i =0;i<m;i++)
{
int temp1,temp2;
scanf("%d %d",&temp1,&temp2);
scanf("%d",&loadw[temp1][temp2]);
loadw[temp2][temp1] = loadw[temp1][temp2];
}
for(int i = 0;i<n;i++)
loadsumw[i] = INF;
然后用Dijkstra算法计算最短路径
void dijkstra(int root)
{
loadsumw[root] = 0;
for(int i = 0;i<n;i++)
{
int temp = -1;
int minn = INF;
for(int j = 0;j<n;j++)
{
if(vis[j]==0&&loadsumw[j]<minn)
{
minn = loadsumw[j];
temp = j;
}
}
if(temp==-1)return;
vis[temp] = 1;
for(int j = 0;j<n;j++)
{
if(vis[j]==0&&loadw[temp][j]!=INF)
{
if (loadsumw[j] > loadsumw[temp] + loadw[temp][j])
{
loadsumw[j] = loadsumw[temp] + loadw[temp][j];
pre[j].clear();
pre[j].push_back(temp);
}
else if (loadsumw[j] == loadsumw[temp] + loadw[temp][j])
{
pre[j].push_back(temp);
}
}
}
}
}
然后用DFS算法求出最短路径中的最小携带或最小携带下的最小剩余,详细的写在了注释上:
void dfs(int end)
{
if(end==0)
{
//如果路径到达了源点
temppath.push_back(end);
int need = 0;
int remain = 0;
for(int i = temppath.size()-1;i>=0;i--)
{
//对这条路上各个节点计算他们所需携带和剩余的车
int temp = temppath[i];
if(nodew[temp]>0)remain+=nodew[temp];
else if(nodew[temp]<0)
{
if(remain>=abs(nodew[temp]))
{
remain+= nodew[temp];
}
else if(remain<abs(nodew[temp]))
{
need =need -nodew[temp]-remain;
remain = 0;
}
}
}
//更新最小携带和最小剩余
if(need<minneed)
{
minneed = need;
minremian = remain;
path = temppath;
}
else if(need==minneed&&remain<minremian)
{
minremian = remain;
path = temppath;
}
temppath.pop_back();
return ;
}
//DFS计算
temppath.push_back(end);
for (int i = 0; i <pre[end].size(); i++)
{
int temp = pre[end][i];
dfs(temp);
}
temppath.pop_back();
}
完整代码如下
#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
#define INF 0x3f3f3f3f
int cmax,n,sp,m;
int nodew[505];
int loadw[505][505];
int loadsumw[505];
int vis[505];
int sum = 0;
vector<int>pre[505];
vector<int>temppath,path;
int minremian = INF,minneed = INF;
void dijkstra(int root)
{
loadsumw[root] = 0;
for(int i = 0;i<n;i++)
{
int temp = -1;
int minn = INF;
for(int j = 0;j<n;j++)
{
if(vis[j]==0&&loadsumw[j]<minn)
{
minn = loadsumw[j];
temp = j;
}
}
if(temp==-1)return;
vis[temp] = 1;
for(int j = 0;j<n;j++)
{
if(vis[j]==0&&loadw[temp][j]!=INF)
{
if (loadsumw[j] > loadsumw[temp] + loadw[temp][j])
{
loadsumw[j] = loadsumw[temp] + loadw[temp][j];
pre[j].clear();
pre[j].push_back(temp);
}
else if (loadsumw[j] == loadsumw[temp] + loadw[temp][j])
{
pre[j].push_back(temp);
}
}
}
}
}
void dfs(int end)
{
if(end==0)
{
temppath.push_back(end);
int need = 0;
int remain = 0;
for(int i = temppath.size()-1;i>=0;i--)
{
int temp = temppath[i];
if(nodew[temp]>0)remain+=nodew[temp];
else if(nodew[temp]<0)
{
if(remain>=abs(nodew[temp]))
{
remain+= nodew[temp];
}
else if(remain<abs(nodew[temp]))
{
need =need -nodew[temp]-remain;
remain = 0;
}
}
}
if(need<minneed)
{
minneed = need;
minremian = remain;
path = temppath;
}
else if(need==minneed&&remain<minremian)
{
minremian = remain;
path = temppath;
}
temppath.pop_back();
return ;
}
temppath.push_back(end);
for (int i = 0; i <pre[end].size(); i++)
{
int temp = pre[end][i];
dfs(temp);
}
temppath.pop_back();
}
int main()
{
scanf("%d%d%d%d",&cmax,&n,&sp,&m);
nodew[0] = 0;
n++;
for(int i = 1;i<n;i++)
{
scanf("%d",&nodew[i]);
nodew[i] = nodew[i]-(cmax/2);
}
for(int i = 0;i<n;i++)
for(int j =0;j<n;j++)
loadw[i][j] = INF;
//cout<<1;
for(int i =0;i<m;i++)
{
int temp1,temp2;
scanf("%d %d",&temp1,&temp2);
scanf("%d",&loadw[temp1][temp2]);
loadw[temp2][temp1] = loadw[temp1][temp2];
}
for(int i = 0;i<n;i++)
loadsumw[i] = INF;
dijkstra(0);
dfs(sp);
printf("%d ",minneed);
for(int i = path.size()-1;i>=0;i--)
{
if(i!=0)printf("%d->",path[i]);
else printf("%d ",path[i]);
}
printf("%d",minremian);
return 0;
}