要求一个最短路,担心的就是一条边被正反经过两次。
规定第一步为1到i,并把这条边设为不可经过。然后从i做最短路到1,因为这个过程是不会经历重边的(如果经历了就不是最短路了)。
求最短路用SPFA,但常数很大,会超时
但YZD大佬轻松优化到0.01s,%%%%YZD大佬orz,方法:
在SPFA时,如果dist+(i->1的路径长)大于ans就没有必要拓展,就不入队
提供YZD大佬博客链接:http://www.cnblogs.com/Lumberjack/
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 struct Node 7 { 8 int next,to,dis; 9 }edge[200001]; 10 int head[50001],num,q[2000001],n,m; 11 int dist[50001],map[50001],ans=2e9; 12 bool vis[50001]; 13 void add(int u,int v,int d) 14 { 15 num++; 16 edge[num].next=head[u]; 17 head[u]=num; 18 edge[num].to=v; 19 edge[num].dis=d; 20 } 21 void SPFA(int x) 22 {int h,t,i; 23 memset(dist,-1,sizeof(dist)); 24 memset(vis,0,sizeof(vis)); 25 q[1]=1; 26 h=0;t=1; 27 dist[1]=0; 28 while (h<t) 29 { 30 h++; 31 int u=q[h]; 32 vis[u]=0; 33 for (i=head[u];i;i=edge[i].next) 34 { 35 int v=edge[i].to; 36 if ((u==1&&v==x)||(u==x&&v==1)) continue; 37 if (dist[u]+edge[i].dis+map[x]<=ans) 38 if (dist[v]>dist[u]+edge[i].dis||dist[v]==-1) 39 { 40 dist[v]=dist[u]+edge[i].dis; 41 if (vis[v]==0) 42 { 43 t++; 44 q[t]=v; 45 vis[v]=1; 46 } 47 } 48 } 49 } 50 } 51 int main() 52 {int i,j,u,v,d,c; 53 //freopen("zaw.in","r",stdin); 54 //freopen("zaw.out","w",stdout); 55 cin>>n>>m; 56 memset(map,127/3,sizeof(map)); 57 for (i=1;i<=m;i++) 58 { 59 scanf("%d%d%d%d",&u,&v,&c,&d); 60 add(u,v,c); 61 add(v,u,d); 62 if (v==1) map[u]=c; 63 if (u==1) map[v]=d; 64 } 65 for (i=2;i<=n;i++) 66 { 67 SPFA(i); 68 if (dist[i]==-1||map[i]==-1) continue; 69 ans=min(ans,map[i]+dist[i]); 70 } 71 cout<<ans<<endl; 72 }