因为有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; }