除看这道题,以为就是很简单的二分+判断负环
但是数次0分告诉我哪有你想的那么简单
我们在求最短路的过程中,应该把那些不同时满足1.与起点联通2.与终点联通的点删除。 一旦我们把这些点考虑进去,且这些点上还有负环时,对答案的影响就是致命的。
比如说这种情况
而如果终点不满足上述条件,我们就可以直接输出-1了。
#include<bits/stdc++.h> using namespace std; const int N=105,M=10005,inf=0x3f3f3f3f; int h[N],e[M],ne[M],w[M]; int tot,n,m,T,dis[N]; bool vis[N],useful[N];//useful表示是否同时满足两个约束条件 inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { x=x*10+ch-'0'; ch=getchar(); } return x*f; } inline void add(int a,int b,int c) { ne[++tot]=h[a]; e[tot]=b; w[tot]=c; h[a]=tot; } inline void dfs(int x) { vis[x]=1; for(int i=h[x];i;i=ne[i]) { int t=e[i]; if(!vis[t])dfs(t); } } inline bool judge(int now,int x) //判断负环 { vis[now]=1; for(int i=h[now];i;i=ne[i]) { int t=e[i]; if(dis[t]>dis[now]+w[i]+x&&useful[t]) { if(vis[t]) return true; //被重复更新,出现负环 dis[t]=dis[now]+w[i]+x; if(judge(t,x)) return true; } } vis[now]=0; return false; } inline void SPFA(int x) { memset(dis,0x3f,sizeof(dis)); memset(vis,0,sizeof(vis)); queue<int> Q; Q.push(1);dis[1]=0;vis[1]=1; while(!Q.empty()) { int tmp=Q.front();Q.pop();vis[tmp]=0; for(int i=h[tmp];i;i=ne[i]) { int t=e[i]; if(dis[t]>dis[tmp]+w[i]+x&&useful[t]) { dis[t]=dis[tmp]+w[i]+x; Q.push(t); vis[t]=1; } } } } inline bool check(int x) { for(int i=1;i<=n;i++) if(useful[i]) { memset(dis,0,sizeof(dis));//判断负环不需要把dis初始化成正无穷 memset(vis,0,sizeof(vis)); if(judge(i,x)) return false; } SPFA(x); if(dis[n]>=0&&dis[n]<=inf) return true; return false; } int main() { T=read(); while(T--) { int ans=0; int l=-1e6,r=1e6; memset(h,0,sizeof(h)); memset(useful,0,sizeof(useful)); tot=0; n=read();m=read(); for(int i=1;i<=m;i++) { int a=read(),b=read(),c=read(); add(a,b,c); } memset(vis,0,sizeof(vis)); dfs(1); for(int i=1;i<=n;i++) if(vis[i]) useful[i]=1; for(int i=1;i<=n;i++) if(useful[i]) { memset(vis,0,sizeof(vis)); dfs(i); if(!vis[n]) useful[i]=0; } if(!useful[n]) //特判 { printf("-1 "); continue; } while(l<r) { int mid=l+r>>1; if(check(mid)) r=mid,ans=dis[n]; else l=mid+1; } printf("%d ",ans); } return 0; }