买房子 | ||||||
| ||||||
Description | ||||||
小W是一个商人并且希望购买一个房子,他发现没有足够的金币去买它。 | ||||||
Input | ||||||
输入的第一行是一个整数T,表示一共有T组测试数据; | ||||||
Output | ||||||
对于每组测试数据,输出购买房子所需要的最少时间,如果不可能则输出-1,每组输出占一行。 | ||||||
Sample Input | ||||||
2 | ||||||
Sample Output | ||||||
7 | ||||||
Author | ||||||
陈禹@HRBUST |
思路:
1、二维最短路,设定dis【i】【j】表示当前走到了i点,而且手上有j金币的最小权值花费。那么理所应当,vis【i】【j】其中ij的含义也是想通的。
2、SPFA求最短路,松弛方程式为:dis【v】【j】=min(dis【v】【j】,dis【u】【j-10】+w【u】【v】);
3、如果我们直接这样求的话,我们最终要在dis【T】【kk-尽可能大】,那么这个尽可能大到底应该确定值为多少呢?其实实际结果是确定值到1000的话也会超时,那么就别想更大的情况了。
4、那么要怎样解决超时问题呢?当j>kk的时候,其实我们直接领j=kk即可。这样,我们就能将所有可以的情况归一,相对的减少了很多的操作。
AC代码:
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
struct node
{
int u,val;
}now,nex;
int head[100000];
struct EdgeNode
{
int to;
int w;
int next;
} e[100000];
bool vis[5005][1005];
int dis[5005][1005];
int n,m,cont;
void add(int from,int to,int w)
{
e[cont].to=to;
e[cont].w=w;
e[cont].next=head[from];
head[from]=cont++;
}
void SPFA(int ss,int tt,int kk)
{
for(int i=0;i<=n;i++)
{
for(int j=0;j<=1000;j++)
{
dis[i][j]=0x3f3f3f3f;
vis[i][j]=0;
}
}
dis[ss][0]=0;
vis[ss][0]=1;
queue<node>s;
now.u=ss;
now.val=0;
s.push(now);
while(!s.empty())
{
now=s.front();
s.pop();
int u=now.u;
int val=now.val;
vis[u][val]=0;
for(int j=head[u];j!=-1;j=e[j].next)
{
int w=e[j].w;
int v=e[j].to;
nex.u=v;nex.val=now.val+10;
if(nex.val>kk)nex.val=kk;
if(dis[nex.u][nex.val]>dis[now.u][now.val]+w)
{
dis[nex.u][nex.val]=dis[now.u][now.val]+w;
if(vis[nex.u][nex.val]==0)
{
vis[nex.u][nex.val]=1;
s.push(nex);
}
}
}
}
if(dis[tt][kk]==0x3f3f3f3f)
{
printf("-1\n");
}
else
printf("%d\n",dis[tt][kk]);
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
cont=0;
memset(head,-1,sizeof(head));
scanf("%d%d",&n,&m);
for(int i=0; i<m; i++)
{
int x,y,w;
scanf("%d%d%d",&x,&y,&w);
add(x,y,w);
add(y,x,w);
}
int s,t,k;
scanf("%d%d%d",&s,&t,&k);
SPFA(s,t,k);
}
}