/*暴力+乱搞 55分(似乎只有暴力得分了)*/ #include<iostream> #include<cstdio> #include<cstring> #include<queue> #include<algorithm> #define maxn 1000010 using namespace std; int n,m,num,head[maxn],dfn[maxn],low[maxn],s[maxn],top,f[maxn]; int sum,topt,c[maxn],dis[maxn],dis2[maxn],vis[maxn],pre[maxn]; int belong[maxn],cir[maxn],ans1=0x7fffffff,ans2=0x7fffffff,D,falg; struct node { int u,v,t,pre; }e[maxn]; void Add(int from,int to,int dis) { num++; e[num].u=from; e[num].v=to; e[num].t=dis; e[num].pre=head[from]; head[from]=num; } void Tarjan(int x) { low[x]=dfn[x]=++topt; s[++top]=x;f[x]=1; for(int i=head[x];i;i=e[i].pre) if(dfn[e[i].v]==0){Tarjan(e[i].v);low[x]=min(low[x],low[e[i].v]);} else if(f[e[i].v]==1)low[x]=min(low[x],dfn[e[i].v]); if(low[x]==dfn[x]) { sum++; while(x!=s[top]) { c[sum]++;f[s[top]]=0; belong[s[top]]=sum;top--; } c[sum]++;f[s[top]]=0; belong[s[top]]=sum;top--; } } void SPFA() { queue<int>q; memset(dis,127/3,sizeof(dis)); memset(vis,0,sizeof(vis)); dis[1]=0;vis[1]=1;q.push(1); while(!q.empty()) { int k=q.front();q.pop();vis[k]=0; for(int i=head[k];i;i=e[i].pre) { int v=e[i].v; if(dis[v]>dis[k]+e[i].t) { dis[v]=dis[k]+e[i].t;pre[v]=k; if(vis[v]==0){vis[v]=1;q.push(v);} } } } } void SPFA2(int si,int ti) { queue<int>q; memset(dis2,127/3,sizeof(dis)); memset(vis,0,sizeof(vis)); dis2[1]=0;vis[1]=1;q.push(1); while(!q.empty()) { int k=q.front();q.pop();vis[k]=0; for(int i=head[k];i;i=e[i].pre) { int v=e[i].v; if(si==k&&ti==v)continue; if(dis2[v]>dis2[k]+e[i].t) { dis2[v]=dis2[k]+e[i].t; if(vis[v]==0){vis[v]=1;q.push(v);} } } } } void Dfs(int x,int d) { if(d>ans1)return; if(x==n&&d!=dis[n]) { ans1=min(ans1,d); return; } for(int i=head[x];i;i=e[i].pre) Dfs(e[i].v,d+e[i].t); } int main() { scanf("%d%d",&n,&m); int x,y,z; for(int i=1;i<=m;i++) { scanf("%d%d%d",&x,&y,&z); if(x==1&&y==n) D=z; Add(x,y,z); } for(int i=1;i<=n;i++) if(dfn[i]==0)Tarjan(i); for(int i=1;i<=n;i++) if(c[belong[i]]>=2)cir[i]=1; SPFA(); int p=n; while(p>1) { if(cir[p]==1)falg=1;p=pre[p]; } if(falg) { Dfs(1,0); if(ans1==0x7fffffff)printf("-1 "); else printf("%d ",ans1); return 0; } p=n; while(p>1) { SPFA2(pre[p],p); if(dis2[n]!=dis[n])ans2=min(ans2,dis2[n]); if(cir[p]==1)ans1=min(ans1,dis[n]+c[belong[p]]); p=pre[p]; } if(D!=dis[n])ans1=min(ans1,D); if(ans2==0x7fffffff&&sum==0)printf("-1 "); else printf("%d ",min(ans1,ans2)); return 0; }
/* 正解. 正反跑spfa 记录每个节点的1跑过来的最短路和n跑过来的最短路 考试的时候想的是每个点的这两个值加起来 然后求此小值 后来发现 样例都过不了..... 原因是 这里的dis数组的定义决定了会忽略一些边 所以 接着这个思路想下来 我们强制走某一条边 也就是我们枚举边 然后计算 disu + dis2v + uv 就是一条路径的长度 注意这里统计出来的数的个数不是路径数 因为同一条路径上的许多边都统计了一遍 但这里求的是严格次短路 这就很好的符合我们求出来的值 只需要找出第二小的不同的就好 也就是说 这种方法不能求次短路 */ #include<iostream> #include<cstdio> #include<cstring> #include<queue> #include<algorithm> #define maxn 200010 using namespace std; int n,m,num,num2,head[maxn],head2[maxn],dis[maxn],dis2[maxn],vis[maxn],ans[maxn],l; int ans1=707406378,ans2=707406378; struct node { int u,v,t,pre; }e[maxn],e2[maxn]; void Add(int from,int to,int dis) { num++; e[num].u=from; e[num].v=to; e[num].t=dis; e[num].pre=head[from]; head[from]=num; } void Add2(int from,int to,int dis) { num2++; e2[num].u=from; e2[num].v=to; e2[num].t=dis; e2[num].pre=head2[from]; head2[from]=num2; } void SPFA() { queue<int>q; memset(dis,127/3,sizeof(dis)); memset(vis,0,sizeof(vis)); dis[1]=0;vis[1]=1;q.push(1); while(!q.empty()) { int k=q.front();q.pop();vis[k]=0; for(int i=head[k];i;i=e[i].pre) { int v=e[i].v; if(dis[v]>dis[k]+e[i].t) { dis[v]=dis[k]+e[i].t; if(vis[v]==0){vis[v]=1;q.push(v);} } } } } void SPFA2() { queue<int>q; memset(dis2,127/3,sizeof(dis)); memset(vis,0,sizeof(vis)); dis2[n]=0;vis[n]=1;q.push(n); while(!q.empty()) { int k=q.front();q.pop();vis[k]=0; for(int i=head2[k];i;i=e2[i].pre) { int v=e2[i].v; if(dis2[v]>dis2[k]+e2[i].t) { dis2[v]=dis2[k]+e2[i].t; if(vis[v]==0){vis[v]=1;q.push(v);} } } } } int main() { scanf("%d%d",&n,&m); int x,y,z; for(int i=1;i<=m;i++) { scanf("%d%d%d",&x,&y,&z); Add(x,y,z);Add2(y,x,z); } SPFA();SPFA2(); for(int i=1;i<=num;i++) { int u=e[i].u;int v=e[i].v; ans[++l]=dis[u]+dis2[v]+e[i].t; } sort(ans+1,ans+1+l); ans1=ans[1]; for(int i=2;;i++) if(ans[i]!=ans1) { ans2=ans[i];break; } if(ans2>=0x7fffffff)printf("-1 "); else printf("%d ",ans2); return 0; }