題意:
從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;
}