想看更多的解题报告:http://blog.csdn.net/wangjian8006/article/details/7870410
转载请注明出处:http://blog.csdn.net/wangjian8006
题目大意:在一张图中,有n个点,有些点之间有通路,并且每个顶点有颜色,'B'和‘P’,当两个顶点的颜色相同,并且有通路才可以走,每个点在每个颜色有一个停留周期,周期过后会变化到下一个颜色
首先给出s与t,代表求s到t的最短时间
再然后有n个结点和m条边,首先这n行代表每个结点会有初始颜色,和再过ric[i]时间就会变化颜色,颜色为'B'的周期时间和颜色为'P'的周期时间。再接下来m条边代表无向边,边权为经过这条边的所用时间
解题思路:一个变形的最短路径,不过要注意的是推算公式,就是已经过了t时间,在v结点到u结点需要最少等待时间能够通行。只要将这个等待时间求出来,再将spfa改下就可以了
/* spfa Memory 540K Time 157MS */ #include <iostream> #include <queue> using namespace std; #define MAXV 310 #define INF 1<<27 #define min(a,b) (a>b?b:a) int s,t,n,m,map[MAXV][MAXV]; int ric[MAXV],tb[MAXV],tp[MAXV]; char c[MAXV]; //这里状态0为B,1为P //查看经过now_time时间后node结点的颜色,以及经过r的时间后会再次变色 int status(int now_time,int node,int &r){ if(c[node]=='B'){ if(now_time-ric[node]<0) {r=ric[node]-now_time;return 0;} now_time=(now_time-ric[node])%(tp[node]+tb[node]); if(now_time<tp[node]) {r=tp[node]-now_time;return 1;} r=tb[node]-now_time+tp[node]; return 0; }else{ if(now_time-ric[node]<0) {r=ric[node]-now_time;return 1;} now_time=(now_time-ric[node])%(tp[node]+tb[node]); if(now_time<tb[node]) {r=tb[node]-now_time;return 0;} r=tp[node]-now_time+tb[node]; return 1; } } //求出已经过了ini_time时间,从start点到end点的最小等待时间 int ti(int ini_time,int start,int end){ int c1,c2,r1,r2; c1=status(ini_time,start,r1); //等待时间,第一步求两个节点经过ini_time后的状态是否一致 c2=status(ini_time,end,r2); if(c1==c2) return 0; //状态一致则不用等待 //如果状态不一致,看两个节点经过ini_time后变到下一个状态的时间是否相同 if(r1!=r2) return min(r1,r2); //时间不同,则返回需要变到下一个时间短的时间即可,因为那样他们状态就相同了 if(c1==0){ //如果时间也相同,那么就看到下下次的状态时间 if(tp[start]<tb[end]) return r1+tp[start]; if(tp[start]>tb[end]) return r2+tb[end]; return -1; }else{ if(tb[start]<tp[end]) return r1+tb[start]; if(tb[start]>tp[end]) return r2+tp[end]; return -1; } } void spfa(){ queue <int>q; int v,i,d[MAXV],tmp; bool vis[MAXV]; memset(vis,false,sizeof(vis)); for(i=0;i<=n;i++) d[i]=INF; d[s]=0; vis[s]=true; q.push(s); while(!q.empty()){ v=q.front();q.pop(); vis[v]=false; for(i=1;i<=n;i++){ tmp=ti(d[v],v,i); //求此路的等待时间,为-1就永远不能经过 if(map[v][i] && tmp!=-1 && d[i]>d[v]+map[v][i]+tmp){ d[i]=d[v]+map[v][i]+tmp; if(!vis[i]){ q.push(i); vis[i]=true; } } } } if(d[t]>=INF) printf("0\n"); else printf("%d\n",d[t]); } int main(){ int i; int a,b,tmp; while(~scanf("%d%d",&s,&t)){ scanf("%d%d",&n,&m); getchar(); for(i=1;i<=n;i++) scanf("%c %d %d %d\n",&c[i],&ric[i],&tb[i],&tp[i]); //记录下结点初始状态,还有多少时间变色,颜色为'B'的存在时间,颜色为'P'的存在时间 for(i=1;i<=m;i++){ //输入m条无向边 scanf("%d%d%d",&a,&b,&tmp); map[b][a]=map[a][b]=tmp; } spfa(); //求最短路径 } return 0; }