最短路集

HNU 11723

http://acm.hnu.cn/online/?action=problem&type=show&id=11723&courseid=155

这是湖大邀请赛的一道题,其实应该算是一道简单题,赛场我从开始一直做到比赛结束,经历了各种错误,re,wa,tle。。。。

这题导致各种错误的原因在于,开始没完全看清楚题意,题意k是x的倍数,但是我却理解成是x段,这里wa了好几次;re的原因在于我想干脆<=k就举出有的路径长度,由于前面没看清题意,数组越界。。无限re。。。。

我重新设计了状态,dp[N][110],表示到该点是x段路的最小长度,然后bfs,虽然状态数不是太多,但是要是有自环的话会循环很多次,就是这里一直使得我在赛场上tle到死,除了这一点,该题的算法是这样的,今天上课子时突然想既然这样的状态会导致死循环,那么反正是要求X倍数的最短路,何不将路段数%x归为一类,这样就只有dp[N][11]种了。。。。。

代码:

#include<iostream> using namespace std ; const int N = 110 ; typedef __int64 LL ; LL map[N][N] ; int n,m,s,t,x ; LL dp[N][11] ; struct Node { int vdx,node ; LL len ; }out,in,all[100000] ; LL bfs() { int head=0,tail=1; in.vdx = s , in.node = 0 ,in.len=0 ; all[0] = in ; dp[s][0] = 0 ; while(head<tail) { out = all[head++] ; for(int i=0;i<n;i++) { if(map[out.vdx][i] != -1) { in.vdx = i ; in.node = (out.node + 1)%x ; in.len = out.len + map[out.vdx][i] ; if(dp[in.vdx][in.node]==-1 || dp[in.vdx][in.node] > in.len) { dp[in.vdx][in.node] = in.len ; all[tail++] = in ; } } } } return dp[t][0] ; } int main() { int a,b,ncas; LL c; scanf("%d",&ncas); while(ncas--) { scanf("%d%d",&n,&m); memset(map,-1,sizeof(map)) ; memset(dp,-1,sizeof(dp)) ; while(m--) { scanf("%d%d%I64d",&a,&b,&c); if(map[a][b] == -1) map[a][b] = c ; else if(map[a][b] > c) map[a][b] = c ; } scanf("%d%d%d",&s,&t,&x) ; if(s == t) { cout<<"0"<<endl ; continue; } LL ans = bfs() ; if(ans == -1) cout<<"No Answer!"<<endl ; else printf("%I64d/n",ans) ; } return 0 ; }

你可能感兴趣的:(最短路集)