题目:https://ac.nowcoder.com/acm/contest/329/B
分析:由于带负权,肯定不能用Dijkstra,用spfa可高效解决,但是特殊 DAG 的性质使得 SPFA 算法无法在规定的时间限内求解出答案,此时由DAG的拓扑序列可以很好解决该问题。
因此,放弃vis数组,以拓扑序列来入队
Ac code:
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
typedef long long ll;
const ll INF=1e10;
vector<pair<int,ll> >edge1[maxn];
vector<pair<int,ll> >edge2[maxn];
ll dis1[maxn],dis2[maxn];
int dg1[maxn],dg2[maxn];
int n;
ll Spfa(int s,ll dis[],int dg[],vector<pair<int,ll> >edge[])
{
queue<int>q;
while(!q.empty()) q.pop();
for(int i=1;i<=n;i++) dis[i]=INF;
dis[s]=0;
for(int i=1;i<=n;i++) if(dg[i]==0) q.push(i);
while(!q.empty()){
int u=q.front();
q.pop();
for(int i=0;i<edge[u].size();i++){
int v=edge[u][i].first;
ll w=edge[u][i].second;
dis[v]=min(dis[v],dis[u]+w);
if(--dg[v]==0)
q.push(v);
}
}
return max(0ll,dis[n]);
}
int main()
{
int t,m;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
for(int i=0;i<=n;i++) edge1[i].clear(),edge2[i].clear();
int u,v;
ll w0,w1,w2;
for(int i=1;i<=m;i++){
scanf("%d%d%lld%lld%lld",&u,&v,&w0,&w1,&w2);
edge1[u].push_back(make_pair(v,-w1+w0)),edge2[u].push_back(make_pair(v,-w2+w0));
dg1[v]++,dg2[v]++;
}
ll ans1=Spfa(1,dis1,dg1,edge1);
ll ans2=Spfa(1,dis2,dg2,edge2);
if(ans1<ans2){
puts("cnznb!!!");
printf("%lld\n",ans2-ans1);
}
else if(ans1>ans2){
puts("rip!!!");
printf("%lld\n",ans1-ans2);
}
else puts("oof!!!");
}
return 0;
}