题意
有一个公共自行车网络,现在你要为公共自行车管理中心(PBMC)查询一下路线,PBMC做为0号节点,除了0号节点外还有n个自行车站点 S i S_i Si,每个自行车站点的自行车容量为C,我们认为一个自行车站有 C 2 \frac{C}{2} 2C辆自行车时是perfect的,现在告诉你这n个站点每个站点的当前自行车数量,并且给你这个网络图的m条边,每条边代表两点之间所需要的时间,题目保证是从0出发的联通图,现在你要求你找到一条从PBMC出发到达 S p S_p Sp的路,并且你需要把这条路上的每一个自行车站点调整为perfect状态,你可以从PBMC送出一些自行车也可以把其中某些数量大于 C 2 \frac{C}{2} 2C的站点中的自行车送到下一个站点,不允许往回送,若最后调整完 S p S_p Sp后还有多余的自行车,还要送回PBMC。对于这条路的要求是时间最短,若有多条最短路,求从PBMC送出最少数量自行车的路,若sent出去的自行车数量还有相同的要求back回来的自行车数量最小的路,题目保证这样的路唯一
思路
首先要求时间最小,那么先跑一遍Dij求最短路所需要的时间,然后剩下的再用dfs去遍历所有到达 S p S_p Sp时间为 l o w c o s t [ S p ] lowcost[S_p] lowcost[Sp]的路,对于每一个路,我们记录下他经过了哪些节点,再计算一下经过这条路,PBMC需要sent多少辆自行车,需要back多少辆自行车,由于调整路上节点的过程是不可逆的,所以一个for可以求出sent和back,记录当前拿走的和补上的数量就可以了,然后记录整个dfs过程中sent最小时back最小的就行了
#include <bits/stdc++.h>
using namespace std;
const int N=505;
const int INF=0x3f3f3f3f;
int cost[N][N];
int lowcost[N];
bool vis[N];
int c[N];
int pre[N];
int ans[N];
int sent=INF;
int back=INF;
int low;
int cnt;
int num;
int C,n,Sp,m;
void Dijstra(int beg)
{
for(int i=0; i<=n; i++)
{
lowcost[i]=INF;
vis[i]=0;
}
lowcost[beg]=0;
for(int j=0; j<=n; j++)
{
int k=-1;
int minn=INF;
for(int i=0; i<=n; i++)
{
if(!vis[i]&&minn>lowcost[i])
{
minn=lowcost[i];
k=i;
}
}
if(k==-1) break;
vis[k]=1;
for(int i=0; i<=n; i++)
{
if(!vis[i]&&lowcost[i]>lowcost[k]+cost[k][i])
{
lowcost[i]=lowcost[k]+cost[k][i];
}
}
}
}
void dfs(int now,int x)
{
if(x==Sp)
{
if(now==low)
{
int s=0;
int h=0;
for(int i=0; i<cnt; i++)
{
if(c[pre[i]]<C&&h==0)
{
s+=C-c[pre[i]];
}
else if(c[pre[i]]<C&&h!=0)
{
if(C-c[pre[i]]<=h)
{
h-=C-c[pre[i]];
}
else
{
s+=C-c[pre[i]]-h;
h=0;
}
}
else if(c[pre[i]]>C)
{
h+=c[pre[i]]-C;
}
}
if(s<sent)
{
sent=s;
back=h;
num=cnt;
for(int i=0; i<cnt; i++)
ans[i]=pre[i];
}
else if(s==sent)
{
if(back>h)
{
back=h;
num=cnt;
for(int i=0; i<cnt; i++)
ans[i]=pre[i];
}
}
}
return;
}
for(int i=0; i<=n; i++)
{
if(!vis[i]&&cost[x][i]!=INF)
{
vis[i]=1;
pre[cnt++]=i;
now+=cost[x][i];
dfs(now,i);
vis[i]=0;
cnt--;
now-=cost[x][i];
}
}
}
int main()
{
scanf("%d%d%d%d",&C,&n,&Sp,&m);
C/=2;
for(int i=1; i<=n; i++)
scanf("%d",&c[i]);
memset(cost,INF,sizeof(cost));
for(int i=0; i<m; i++)
{
int u,v,c;
scanf("%d%d%d",&u,&v,&c);
cost[u][v]=cost[v][u]=c;
}
Dijstra(0);
low=lowcost[Sp];
memset(vis,0,sizeof(vis));
vis[0]=1;
dfs(0,0);
printf("%d 0",sent);
for(int i=0; i<num; i++)
printf("->%d",ans[i]);
printf(" %d\n",back);
return 0;
}