JOI 所住的城市有 N 个车站,分别编号为 1::N。有 M条铁路,编号为 1..M。第I 条铁路双向连接车站 A 与车站 B,乘车费用为 C。
JOI 住在车站 S 附近,而 JOI 所在的 IOI 高中在车站 T 附近。他打算买一张月票往返这两个车站。当他买这张月票时,他需要选择一条在车站 S 与车站 T之间的乘车费用最小的路径。有了这张月票,JOI 可以无需额外费用,双向通过任意所选路径包含的铁路。
JOI 经常去在车站 U 与车站 V 附近的书店,因此他希望能买一张月票使得从车站 U 到车站 V 的花费最小。
当他要从车站 U 去往车站 V 时,他会选择一条从车站 U 到车站 V 的路径。对于路径上的每段铁路,如果这段铁路在月票指定的路径范围内,则费用为 0 ,否则费用为C 。每段铁路的费用和为 JOI 从车站 U 到车站 V 的总费用。
他想要知道,如果他买月票时选择了一条合适的路线,从车站 U到车站 V 的最小费用是多少。
你需要编写一个程序计算最小费用。
解:
真是一道好题目啊
首先我们有一个贪心策略 首先将所有最短路上的边设置为有向边 然后再跑最短路 但是这样做有问题 因为两条路可能在两条最短路上 这就很难受了
但是!!! 注意到 这是一条连续的路径 最短路的边一定是DAG DAG上搞事情 DP啊 最短路的题目 不是建立图就是考DP 想DP 而且是一个在最短路上搞的DP 注意到 题目的条件是在一条最短路上 而一条最短路的条件为 (dis[u]==dis[v]+le[i])然后我们就可以DP了 在图上的DP一定是在一个top序列上DP 于是我们就想到了 将最短路作为top序列进行DP 具体实现可以利用(dij)来做
topp序列DAG DP
queue<int> q;
void DP() {
for (int i = 1; i <= n; fu[i] = vu[i], fv[i] = vv[i], i++)
if (!deg[i])
q.push(i);
while (q.size()) {
int x = q.front();
q.pop();
ans = min(ans, min(fv[x] + vu[x], fu[x] + vv[x]));
for (int i = las[x]; i; i = pre[i]) {
int y = to[i];
fu[y] = min(fu[y], fu[x]), fv[y] = min(fv[y], fv[x]);
if (--deg[y] == 0)
q.push(y);
}
}
}
code:
//
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inf (ll)(1e17)
#define maxnn 2010000
ll las[maxnn],nex[maxnn],le[maxnn],tot,en[maxnn];
ll zlas[maxnn],znex[maxnn],zle[maxnn],ztot,zen[maxnn];
ll flas[maxnn],fnex[maxnn],fle[maxnn],ftot;
ll dis1[maxnn],dis2[maxnn],dis3[maxnn],dis4[maxnn];
ll n,m,s,t,u,v;
struct node
{
int st,en;
ll l;
ll d;
}ed[maxnn];
int cnt;
void add(int a,int b,ll c)
{
en[++tot]=b;
nex[tot]=las[a];
las[a]=tot;
le[tot]=c;
}
void zadd(int a,int b,ll c)
{
zen[++ztot]=b;
znex[ztot]=zlas[a];
zlas[a]=ztot;
zle[ztot]=c;
}
typedef pair<ll ,int > P;
priority_queue<P ,vector<P>,greater<P> > Q;
void dij(ll *dis,int v)
{
for(int i=1;i<=n;i++)
{
dis[i]=inf;
}
dis[v]=0;
Q.push(make_pair(dis[v],v));
while(Q.size())
{
P s=Q.top();
Q.pop();
if(s.first!=dis[s.second]) continue;
for(int i=las[s.second];i;i=nex[i])
{
int u=en[i];
if(dis[u]>dis[s.second]+le[i])
{
dis[u]=dis[s.second]+le[i];
Q.push(make_pair(dis[u],u));
}
}
}
}
ll dis[maxnn];
ll f[maxnn][3];
ll ans=111111111000000;
void ddij(int v)
{
for(int i=1;i<=n;i++)
{
f[i][0]=f[i][1]=inf;
}
for(int i=1;i<=n;i++)
{
dis[i]=inf;
}
dis[v]=0;
f[v][0]=dis3[v];
f[v][1]=dis4[v];
Q.push(make_pair(dis[v],v));
while(Q.size())
{
P s=Q.top();
Q.pop();
if(s.first!=dis[s.second]) continue;
for(int i=zlas[s.second];i;i=znex[i])
{
int u=zen[i];
if(dis[u]==dis[s.second]+zle[i])
{
dis[u]=dis[s.second]+zle[i];
f[u][0]=min(f[u][0],min(f[s.second][0],dis3[u]));
f[u][1]=min(f[u][1],min(f[s.second][1],dis4[u]));
}
if(dis[u]>dis[s.second]+zle[i])
{
dis[u]=dis[s.second]+zle[i];
f[u][0]=min(f[s.second][0],dis3[u]);
f[u][1]=min(f[s.second][1],dis4[u]);
Q.push(make_pair(dis[u],u));
}
}
}
}
int main()
{
ll x,y,z;
scanf("%lld%lld%lld%lld%lld%lld",&n,&m,&s,&t,&u,&v);
for(int i=1;i<=m;i++)
{
scanf("%lld%lld%lld",&x,&y,&z);
add(x,y,z);
add(y,x,z);
ed[++cnt].st=x;
ed[cnt].en=y;
ed[cnt].l=z;
}
dij(dis1,s);
dij(dis2,t);
dij(dis3,u);
dij(dis4,v);
for(int i=1;i<=cnt;i++)
{
if(dis1[ed[i].st]+dis2[ed[i].en]+ed[i].l==dis1[t])
{
zadd(ed[i].st,ed[i].en,ed[i].l);
}
if(dis1[ed[i].en]+dis2[ed[i].st]+ed[i].l==dis1[t])
{
zadd(ed[i].en,ed[i].st,ed[i].l);
}
}
ddij(s);
for(int i=1;i<=n;i++)
{
ans=min(ans,f[i][1]+dis3[i]);
ans=min(ans,f[i][0]+dis4[i]);
}
ans=min(ans,dis3[v]);
cout<<ans;
}