回家Ⅱ | ||||||
| ||||||
Description | ||||||
lz买了个新车,现在他想开着车回到家里,但是回家的道路没有直达的,所以他必须经过一些城市。 一开始,车上只有他自己一个人(lz从编号为1的城市出发),车的行驶速度为每单位距离花费1单位的时间,但是当车上有x个人的时候,每单位的距离将花费x单位的时间。每座城市都住着lz的一个朋友,每次经过一个城市的时候,就会有一个朋友坐上车和lz一起回到家中(出发的城市不会有朋友上车),但是lz想早点回到家(编号为n的城市),请帮助lz计算出回到家最少要花多少时间。 | ||||||
Input | ||||||
多组测试数据。 每组测试数据第一行输入两个正整数 n , m (0 < n ≤ 200, 0 < m < n×(n-1)/2 ), n 代表城市的数量,m表示现有道路的数量。 接下来的m行,每行输入三个整数x,y,z表示x,y城市之间有一条长度为z个单位距离的双向道路。 | ||||||
Output | ||||||
对于每组数据输出一个整数表示lz回到家的最少时间,每组输出占一行。 | ||||||
Sample Input | ||||||
3 2
| ||||||
Sample Output | ||||||
5
| ||||||
Author | ||||||
`Wind @hrbust |
思路:
1、首先想到裸SPFA,样例过掉了,但是仔细YY了一下,判vis【】的时候,会误判当前情况的入队于否,然后找了两组样例,果然对不上。
2、既然一维判重过不掉,那我们就二维判重,令误判了的入队于否的情况,使其变得正确了就好辣!
3、以后有限制的最短路,再也不敢用一维判重辣T T !!!以后有限制的最短路,再也不敢直接开一维dis【】辣!!!
AC代码:
#include<stdio.h>
#include<queue>
#include<string.h>
using namespace std;
struct node
{
int u,cur;
}now,nex;
struct EdgeNode
{
int to;
int w;
int next;
}e[1000000];
int head[210];
int vis[210][5000];
int ansdis[210];
int dis[210][5000];
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)
{
for(int i=1;i<=n;i++)ansdis[i]=0x3f3f3f3f;
memset(dis,0x3f3f3f3f,sizeof(dis));
memset(vis,0,sizeof(vis));
queue<node >s;
now.cur=1;
now.u=ss;
s.push(now);
vis[now.u][1]=1;
dis[now.u][1]=0;
ansdis[now.u]=0;
while(!s.empty())
{
now=s.front();
s.pop();
vis[now.u][now.cur]=0;
int u=now.u;
int cur=now.cur;
for(int j=head[u];j!=-1;j=e[j].next)
{
int v=e[j].to;
int w=e[j].w;
if(ansdis[v]>dis[u][cur]+w*cur)
{
dis[v][cur+1]=dis[u][cur]+w*cur;
ansdis[v]=dis[v][cur+1];
if(vis[v][cur+1]==0)
{
nex.u=v;
nex.cur=now.cur+1;
s.push(nex);
vis[v][cur+1]=1;
}
}
}
}
printf("%d\n",ansdis[n]);
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
cont=0;
memset(head,-1,sizeof(head));
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);
}
SPFA(1);
}
}
/*
8 10
1 2 2
2 5 4
1 3 1
3 5 4
3 6 1
6 5 1
5 7 4
5 4 1
4 8 2
7 8 1
*/