发现SPFA真的是差不多可以用在大多数的最短路问题上了
就连10的5次方也可以500ms过~
超级好用的算法~~
然后发现数组的大小开的真的很关键,大了MLE,小了就超时。。血的教训
还是很奇怪的是inf = 0x3f3f3f3f 少了一个3f就会出错,真是奇怪!!
最后就是读题目啊啊啊真的是要理解题意,~~~~
这道题大概就是每个点都属于某一层,相邻的层的点可以以c的value相通,后面再给出其他可以互通的M条边
怎么建图~是个问题。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = 200005;
int Left[maxn*20],Right[maxn*20],key[maxn*20],Next[maxn*20],n,m,c,num[maxn],cnt;
int dict[maxn];
bool vis[maxn],vv[maxn];
void init() {
cnt = 0;
memset(vis,false,sizeof(vis));
memset(Left,-1,sizeof(Left));
memset(vv,false,sizeof(vv));
}
void add(int u,int v,int value) {
key[cnt] = value;
Next[cnt] = Left[u];
Left[u] = cnt;
Right[cnt] = v;
cnt++;
}
queue<int> q;
void SPFA() {
memset(dict,inf,sizeof(dict));
dict[1] =0;
vis[1] = true;
while(!q.empty()) q.pop();
q.push(1);
while(!q.empty()) {
int temp = q.front();
q.pop();
vis[temp] = false;
for(int i = Left[temp];i != -1;i = Next[i]) {
if(dict[Right[i]] > dict[temp] + key[i]) {
dict[Right[i]] = dict[temp] + key[i];
if(!vis[Right[i]]) {
//printf("%d-\n",Right[i]);
vis[Right[i]] = true;
q.push(Right[i]);
}
}
}
}
if(dict[n] >= inf) {
printf("-1\n");
return ;
}
printf("%d\n",dict[n]);
return ;
}
int main() {
//freopen("heiheihei.txt","r",stdin);
int T;
scanf("%d",&T);
for(int l = 1;l <= T;l++) {
scanf("%d%d%d",&n,&m,&c);
init();
int u;
for(int i = 1;i <= n;i++)
{
scanf("%d",&u);
num[i]=u;
vv[u]=1;
}
for(int i = 1;i < n;i++)
{
if(vv[i] && vv[i+1])
{
add(n+i,n+i+1,c);
add(n+i+1,n+i,c);
}
}
for(int i = 1;i <= n;i++)
{
add(n+num[i],i,0);
if(num[i] > 1) add(i,n+num[i]-1,c);
if(num[i] < n) add(i,n+num[i]+1,c);
}
for(int i = 1;i <= m;i++) {
int v,value;
scanf("%d%d%d",&u,&v,&value);
add(u,v,value);
add(v,u,value);
}
printf("Case #%d: ",l);
SPFA();
}
return 0;
}