Note
- Dijkstra+DFS
- 邻接矩阵
- 注意看清题目要求 :先按send最小,若仍不唯一,按back最小。
- 测试点5&7:
只能沿着最短路径的方向收集多余自行车,分给后面的节点,后面节点多出来的不能填到前面去,只能计入回收总量。
例如路径上自行车数为5->0->10,并不能把最后一个节点上挪5个给中间的,需要送出5个,并回收5个。所以总需求量不能用Cmax / 2 * 节点数 - 现有数来计算。
Code
#include<bits/stdc++.h>
using namespace std;
const int INF=1e9;
int cmax,n,sp,m;
int current[505],graph[505][505],dist[505];
bool vis[505]={false};
vector<int> pre[505];
int min_send=1e9,min_back=1e9;
vector<int> temp,ans;
void dijkstra(int s){
fill(dist,dist+505,INF);
dist[s]=0;
for(int i=0;i<=n;i++){
int u=-1,min=INF;
for(int j=0;j<=n;j++){
if(vis[j]==false&&dist[j]<min){
min=dist[j];
u=j;
}
}
if(u==-1) return ;
vis[u]=true;
for(int j=0;j<=n;j++){
if(vis[j]==false&&graph[u][j]!=INF){
if(dist[u]+graph[u][j]<dist[j]){
dist[j]=dist[u]+graph[u][j];
pre[j].clear();
pre[j].push_back(u);
}
else if(dist[u]+graph[u][j]==dist[j])
pre[j].push_back(u);
}
}
}
}
void dfs(int start,int end){
if(start==end){
int bac=0,sec=0;
for(int i=temp.size()-1;i>=0;i--){
int cnt=current[temp[i]];
if(cnt>=cmax) bac=bac+cnt-cmax;
else{
int diff=cmax-cnt;
if(diff>bac){
sec=sec+diff-bac;
bac=0;
}
else bac-=diff;
}
}
if(sec<min_send){
min_back=bac;
min_send=sec;
temp.push_back(start);
ans=temp;
temp.pop_back();
}
else if(sec==min_send&&bac<min_back){
min_back=bac;
min_send=sec;
temp.push_back(start);
ans=temp;
temp.pop_back();
}
return ;
}
temp.push_back(end);
for(int i=0;i<pre[end].size();i++)
dfs(start,pre[end][i]);
temp.pop_back();
return ;
}
int main(){
#ifndef ONLINE_JUDGE
freopen("data.txt","r",stdin);
#endif
fill(graph[0],graph[0]+505*505,INF);
int si,sj,tij;
scanf("%d %d %d %d",&cmax,&n,&sp,&m);
cmax/=2;
for(int i=1;i<=n;i++)
scanf("%d",¤t[i]);
for(int i=1;i<=m;i++){
scanf("%d %d %d",&si,&sj,&tij);
graph[si][sj]=tij;
graph[sj][si]=tij;
}
dijkstra(0);
dfs(0,sp);
printf("%d ",min_send);
for(int i=ans.size()-1;i>=0;i--){
printf("%d",ans[i]);
if(i!=0) printf("->");
}
printf(" %d\n",min_back);
return 0;
}