因为有c值的存在 不满足dp的后效性 所以不能直接跑最短路
要把边抽象为点 将t值当做每个点的点权 每两个点的c值之差当做边权 出发点就是原图中所有和1相连的边对应的点 建立一个超级源点 连向这几个点 目标点就是原图中所有和n相连的边对应的点
还有建图的问题 再建一个新图非常耗时(貌似会比原图稠密很多 比如星形图) 我们可以直接利用原图来跑最短路 详见代码
这道题的复杂度问题有点迷 用spfa就会T 还有就是星形图了 样例中应该是没有 否则dijkstra照样会T吧
#include <cstdio>
#include <queue>
#include <cstring>
#include <algorithm>
using namespace std;
#define ll long long
#define N 0x3f3f3f3f3f3f3f3f
struct node1
{
int u;
int v;
ll c;
ll t;
};
struct node2
{
int id;
int v;
int next;
};
struct node3
{
bool friend operator < (node3 n1,node3 n2)
{
return n1.val>n2.val;
}
int id;
ll val;
};
priority_queue <node3> que;
node1 pre[100010];
node2 edge[200010];
ll point[100010],dis[100010];
int first[100010],book[100010];
int n,m,num;
void addedge(int id,int u,int v)
{
edge[num].id=id;
edge[num].v=v;
edge[num].next=first[u];
first[u]=num++;
return;
}
ll getabs(ll a,ll b)
{
if(a>=b) return a-b;
else return b-a;
}
ll dijkstra()
{
node3 cur,tem;
ll w,minn;
int i,u,v;
while(!que.empty()) que.pop();
memset(dis,0x3f,sizeof(dis));
memset(book,0,sizeof(book));
tem.id=m+1,tem.val=0;
que.push(tem);
dis[m+1]=0;
while(!que.empty())
{
cur=que.top();//An edge
que.pop();
u=cur.id;
if(book[u]) continue;
book[u]=1;
//printf("***%d %lld***\n",u,dis[u]);
for(i=first[pre[u].u];i!=-1;i=edge[i].next)
{
v=edge[i].id;//Another edge
if(pre[u].c!=-1) w=getabs(pre[u].c,pre[v].c);
else w=0;
if(!book[v]&&dis[v]>dis[u]+w+pre[u].t)
{
dis[v]=dis[u]+w+pre[u].t;
tem.id=v,tem.val=dis[v];
que.push(tem);
//printf("*%d %lld*\n",v,dis[v]);
}
}
for(i=first[pre[u].v];i!=-1;i=edge[i].next)
{
v=edge[i].id;//Another edge
if(pre[u].c!=-1) w=getabs(pre[u].c,pre[v].c);
else w=0;
if(!book[v]&&dis[v]>dis[u]+w+pre[u].t)
{
dis[v]=dis[u]+w+pre[u].t;
tem.id=v,tem.val=dis[v];
que.push(tem);
//printf("*%d %lld*\n",v,dis[v]);
}
}
}
minn=N;
for(i=first[n];i!=-1;i=edge[i].next)
{
v=edge[i].id;
minn=min(minn,dis[v]+pre[v].t);
}
return minn;
}
int main()
{
int i;
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(first,-1,sizeof(first));
num=0;
for(i=1;i<=m;i++)
{
scanf("%d%d%lld%lld",&pre[i].u,&pre[i].v,&pre[i].c,&pre[i].t);
addedge(i,pre[i].u,pre[i].v);
addedge(i,pre[i].v,pre[i].u);
}
pre[m+1].u=0,pre[m+1].v=1,pre[m+1].c=-1,pre[i].t=0;
addedge(m+1,n+1,1);
printf("%lld\n",dijkstra());
}
return 0;
}