n个点,m条边,给起点和终点,求起点到终点的最小花费,每个点都有两种状态,每个点的每种状态都有一个持续的时间,只有在某条边连接的两个点状态相同时这条边才可走。实际上就是一个带限制的最短路,每次松弛的时候,花费就是边的花费加上最少要等多长时间两个点的颜色会变成相同..如果永远无法相同,这条边就不能走了...思路很简单,时间的处理写起来比较恶心....
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <memory.h>
#include <cmath>
#include <string>
#include <cstring>
#include <queue>
#include <stack>
using namespace std;
typedef long long ll;
const int inf=(1<<28);
const int maxn=330;
int n,m,tt,p;
int st,ed;
struct EDGE
{
int v,w,next;
}edge[30000];
int g[maxn];
int ne;
struct Light
{
bool type;
int res,t1,t2;
}light[maxn];
int pre[maxn];
bool vis[maxn];
int dis[maxn];
int slove(int src)
{
memset(vis,false,sizeof vis);
memset(pre,0,sizeof pre);
for (int i=0; i<=n; i++) dis[i]=inf;
dis[src]=0;
queue<int>q;
q.push(src);
vis[src]=true;
while(!q.empty())
{
int u,v;
int t1,t2;
bool f1,f2;
u=q.front();
int now=dis[u];
int cost=0;
q.pop();
vis[u]=false;
for(int j=g[u]; j!=-1; j=edge[j].next)
{
v=edge[j].v;
cost=edge[j].w;
t1=now-light[u].res;
if (t1<0) f1=light[u].type,t1=light[u].res-now;
else {
t1=t1 % (light[u].t1+light[u].t2);
if (!light[u].type)
{
if (t1>=light[u].t2) f1=0,t1=light[u].t1+light[u].t2-t1;
else f1=1,t1=light[u].t2-t1;
}
else
{
if (t1>=light[u].t1) f1=1,t1=light[u].t1+light[u].t2-t1;
else f1=0,t1=light[u].t1-t1;
}
}
t2=now-light[v].res;
if (t2<0) f2=light[v].type,t2=light[v].res-now;
else
{
t2=t2 % (light[v].t1+light[v].t2);
if (!light[v].type)
{
if (t2>=light[v].t2) f2=0,t2=light[v].t1+light[v].t2-t2;
else f2=1,t2=light[v].t2-t2;
}
else
{
if (t2>=light[v].t1) f2=1,t2=light[v].t1+light[v].t2-t2;
else f2=0,t2=light[v].t1-t2;
}
}
if (f1==f2)
{
if (dis[v]>cost+dis[u])
{
dis[v]=dis[u]+cost;
pre[v]=u;
if (!vis[v]){
q.push(v);
vis[v]=true;
}
}
}
else
{
bool ok=true;
if (t1!=t2) cost+=min(t1,t2);
else
{
f1^=1;
f2^=1;
cost+=t1;
if (!f1) t1=light[u].t1;
else t1=light[u].t2;
if (!f2) t2=light[v].t1;
else t2=light[v].t2;
if (t1!=t2) cost+=min(t1,t2);
else
{
f1^=1;
f2^=1;
cost+=t1;
if (!f1) t1=light[u].t1;
else t1=light[u].t2;
if (!f2) t2=light[v].t1;
else t2=light[v].t2;
if (t1!=t2) cost+=min(t1,t2);
else ok=false;
}
}
if (ok)
{
if (dis[v]>dis[u]+cost)
{
dis[v]=dis[u]+cost;
pre[v]=u;
if (!vis[v])
{
q.push(v);
vis[v]=true;
}
}
}
}
}
}
return dis[ed];
}
void find(int u)
{
if (u==0) return;
find(pre[u]);
if (u==st)
printf("%d",u);
else printf(" %d",u);
}
int main()
{
// freopen("in.txt","r",stdin);
while(~scanf("%d%d",&st,&ed))
{
scanf("%d%d",&n,&m);
char s[5];
for (int i=1; i<=n; i++)
{
scanf("%s",&s);
light[i].type=(s[0]=='P');
scanf("%d%d%d",&light[i].res,&light[i].t1,&light[i].t2);
}
ne=0;
int x,y,z;
memset(g,-1,sizeof g);
for (int i=1; i<=m; i++)
{
scanf("%d%d%d",&x,&y,&z);
edge[ne].v=y;
edge[ne].next=g[x];
edge[ne].w=z;
g[x]=ne;
ne++;
edge[ne].v=x;
edge[ne].next=g[y];
edge[ne].w=z;
g[y]=ne;
ne++;
}
int out=slove(st);
if (out<inf)
{
printf("%d\n",out);
find(ed);
printf("\n");
}
else puts("0");
}
return 0;
}