差分约束系统。
由题意直接可以得到一系列不等式,直接可以建图跑最短路。
如果存在负环,那么输出-1,如果1到n的最短路距离无穷大,那么输出-2,其余输出1到n的最短路距离。
关于查分约束系统可以看这篇博客http://www.cnblogs.com/void/archive/2011/08/26/2153928.html
#include<cstdio> #include<cstring> #include<cmath> #include<vector> #include<queue> #include<algorithm> using namespace std; const long long INF=9223372036854775807; const int maxn=1000+10; int n,ml,md; struct Edge { int u,v; long long cost; }e[20*maxn]; vector<int>G[maxn]; bool flag[maxn]; long long dis[maxn]; int tot[maxn]; long long ans; void init() { for(int i=1;i<=n;i++) G[i].clear(); memset(flag,0,sizeof flag); memset(tot,0,sizeof tot); for(int i=1;i<=n;i++) dis[i]=INF; ans=-3; } void read() { for(int i=1;i<=ml;i++) { int a,b; long long d; scanf("%d%d%lld",&a,&b,&d); e[i].u=a; e[i].v=b; e[i].cost=d; G[a].push_back(i); } for(int i=1;i<=md;i++) { int a,b; long long d; scanf("%d%d%lld",&a,&b,&d); e[i+ml].u=b; e[i+ml].v=a; e[i+ml].cost=-d; G[b].push_back(i+ml); } } void SPFA() { queue<int>Q; flag[1]=1; dis[1]=0; Q.push(1); while(!Q.empty()) { int head=Q.front(); Q.pop(); flag[head]=0; tot[head]++; if(tot[head]>n) {ans=-1; break;} for(int i=0;i<G[head].size();i++) { int id=G[head][i]; int to=e[id].v; long long c=e[id].cost; if(dis[head]+c<dis[to]) { dis[to]=dis[head]+c; if(!flag[to]) { flag[to]=1; Q.push(to); } } } } if(ans!=-1) { if(dis[n]==INF) ans=-2; else ans=dis[n]; } printf("%lld ",ans); } int main() { while(~scanf("%d%d%d",&n,&ml,&md)) { init(); read(); SPFA(); } return 0; }