51,716
社区成员




接昨天的模板
P7655 [BalticOI 1996 Day 2] A FAST JOURNEY - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
//奇数天正走 偶数天反走
//由于求得是最优解,当前边只要走过就不会再走了,且该边如果在整条路上的话会优先在靠前的位置使用,所以只需要奇偶即可
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int N=110, M=2020;
int a,b,n,k,m;
bool vis[N][2][20];//天数是不确定的,可是天数的奇偶性是确定的,通过奇偶性可以得到是正边还是反边
int cntp[N],cntx[N],cntd[N],cntt[N];//出发编号 到达编号 日期 道路长度
int h[N],e[M],ne[M],w[M],f[M],idx;//链头 下一个点 next指针 权值 正反边 id
int pre[N],ddd[N],ttt[N],t1[M];//上一个点 当前点所在第几天 当前点花费当天的总时间 当前点花费的时间
struct Node
{
int point,day,time;
bool operator < (const Node &W) const
{
//优先天数比较,其次时间比较(时间上限是12)
if(day==W.day) return time > W.time;
return day > W.day;
}
};
//邻接表
void add(int a,int b,int c,int xx)
{
e[++idx]=b, w[idx]=c, ne[idx]=h[a], h[a]=idx, f[idx]=xx;
}
void out(int x,int &m)
{
if(x==a) return; //出口
//反向遍历整条路
cntp[++m]=pre[x];
cntx[m]=x;
cntd[m]=ddd[x];
cntt[m]=t1[x];
out(pre[x],m);
}
void dijkstra()
{
priority_queue<Node> q;
memset(ddd,0x3f,sizeof ddd);
memset(ttt,0x3f,sizeof ttt);
q.push((Node){a,1,0});//起点第一天时间0
while(q.size())
{
Node u=q.top(); q.pop();
int p=u.point, d=u.day, t=u.time;
if(p==b)
{
out(b,m);
for(int i=m; i>0; i--)
printf("%d %d %d %d\n",cntp[i],cntx[i],cntd[i],cntt[i]);
return ;
}
if(vis[p][d%2][t]) continue;
vis[p][d%2][t]=1;
//留在当前点一天
if(!vis[p][(d+1)%2][0]) q.push((Node){p,d+1,0});
for(int i=h[p]; i; i=ne[i])
{
int v=e[i], tt=w[i];
//不足一天 当前边所处时间一致且未标记的性质
if(tt+t<=12 && d%2==f[i] && !vis[v][d%2][t+tt])
{
//花费的天数较少 或者 天数一致花费的时间较少
if(d<ddd[v] || (d==ddd[v] && t+tt<ttt[v]))
{
pre[v]=p; //p->v
ddd[v]=d;
t1[v]=tt;
ttt[v]=t+tt; //更新v点的前置 第几天 时间 总花费时间
q.push((Node){v,d,t+tt});
}
}
}
}
}
int main()
{
cin>>a>>b;
cin>>n>>k;
while(k--)
{
int a,b,c;
cin>>a>>b>>c;
add(a,b,c,1);//正向建边
add(b,a,c,0);//反向建边
}
dijkstra();
return 0;
}