题意:
从0号点到给定的有问题的点en,要保证每个点自行车数量为Cmax的一半,一个点的自行车数量可以被这条路径上前几个点多的自行车来补. 问你从0到问题点en的最短路径,如果最短路径相同,输出需要从0点携带的自行车数量最小的路径,如果还相同输出该路径上需要带回去最少的路径。(需要将路径上经过的所有点的自行车数量都变为完美的)
思路:
如果单纯的路径最短,或者带出来的自行车数量最小还可以用最短路算法贪心的做,现在要同时维护三个好像不太好处理了,对于这个题目我们先用最短路求出0到问题点en的最短路径,然后从0点开始dfs暴力找到所有等于最短路径的路径(这个过程记录下路径),然后判断一下哪个最优就行了.(也可以直接爆搜,维护最短路径)
#include<bits/stdc++.h>
#define pb push_back
#define inf 0x3f3f3f3f
using namespace std;
const int maxn = 5e2+5;
struct node
{
int to,cost;
node(int x = 0,int y = 0)
{
to = x,cost = y;
}
};
int cm,n,m,en;
vector<node>vt[maxn];
int val[maxn],vis[maxn];
int dis[maxn];
int m_send,m_take_back;
vector<int>ans,path;
void dij(int st,int dt)
{
for(int i = 0;i <= n;++i)
{
dis[i] = inf;
vis[i] = 0;
}
dis[st] = 0;
queue<int>Q;
while(!Q.empty()) Q.pop();
Q.push(st);
vis[st] = 1;
while(!Q.empty())
{
int cur = Q.front();Q.pop();
vis[cur] = 0;
for(int i = 0;i < vt[cur].size();++i)
{
int to = vt[cur][i].to;
int cost = vt[cur][i].cost;
if(dis[to] > dis[cur] + cost)
{
dis[to] = dis[cur] + cost;
if(!vis[to])
{
Q.push(to),vis[to] = 1;
}
}
}
}
return ;
}
bool book[maxn];
void dfs(int cur,int s)
{
if(s > dis[en]) return ;
if(cur == en)
{
int need = 0,take_back = 0;
if(s == dis[en])
{
for(int i = 0;i < path.size();++i)
{
if(val[path[i]] > 0)
take_back += val[path[i]];
else
{
if(take_back > 0)
{
if(take_back >= abs(val[path[i]]))
take_back -= abs(val[path[i]]);
else
{
need += abs(val[path[i]]) - take_back;
take_back = 0;
}
}
else
need += abs(val[path[i]]);
}
}
}
if(need < m_send)
{
m_send = need;
m_take_back = take_back;
ans = path;
}
else if(need == m_send && take_back < m_take_back)
{
m_send = need;
m_take_back = take_back;
ans = path;
}
}
for(int i = 0;i < vt[cur].size();++i)
{
int v = vt[cur][i].to;
int cost = vt[cur][i].cost;
if(!vis[v])
{
vis[v] = 1;
path.pb(v);
dfs(v,s + cost);
vis[v] = 0;
path.pop_back();
}
}
return ;
}
int main()
{
while(~scanf("%d %d %d %d",&cm,&n,&en,&m))
{
cm /= 2;
for(int i = 0;i <= n;++i)
vt[i].clear();
for(int i = 1;i <= n;++i)
scanf("%d",&val[i]),val[i] -= cm;
val[0] = 0;
for(int i = 0;i < m;++i)
{
int a,b,c;
scanf("%d %d %d",&a,&b,&c);
vt[a].pb(node(b,c));
vt[b].pb(node(a,c));
}
dij(0,en);
m_send = m_take_back = inf;
ans.clear();
path.clear();
memset(book,0,sizeof book);
path.pb(0);
book[0] = 1;
dfs(0,0);
printf("%d ",m_send);
for(int i = 0;i < ans.size();++i)
{
if(i == 0) printf("0");
else
printf("->%d",ans[i]);
}
printf(" %d\n",m_take_back);
}
return 0;
}