题目链接:传送门
思路:因为存在负值边,所以一开始就想广搜求出最短路径,结果错了,后来发现是没用好bfs。
题解上说可以用拓扑排序求带负权值边的最短路径,这次get到了。
就是邻接表的使用还不太熟悉,代码是参考排名第一的大佬的。
#include<iostream> #include<cstdio> #include<cstring> #include<queue> #include<algorithm> using namespace std; typedef long long LL; const int maxn = 2e5+10; const int INF = 0x3f; int u[maxn],v[maxn],c[maxn],ai[maxn],bi[maxn]; int head[maxn],rd[maxn],tot,m,n; LL dis[maxn]; struct Node{ int id,nxt; LL data; }edge[maxn]; void Init() { tot=1; memset(rd,0,sizeof(rd)); memset(head,-1,sizeof(head)); memset(dis,INF,sizeof(dis)); } Node tmp; void addedge(int x,int y,LL dd) { tmp.id=y;tmp.data=dd;tmp.nxt=head[x]; edge[tot]=tmp; head[x]=tot++; rd[y]++; } LL bfs() { queue <int> q; int i,j; dis[1]=0; for(i=1;i<=n;i++) if(rd[i]==0) q.push(i); while(!q.empty()) { int u=q.front(); q.pop(); for(i=head[u];i!=-1;i=edge[i].nxt) { int v=edge[i].id; if(dis[v]>dis[u]+edge[i].data) dis[v]=dis[u]+edge[i].data; rd[v]--; if(rd[v]==0) q.push(v); } } return dis[n]; } LL MAX(LL x,LL y) { return x>y?x:y; } int main(void) { int T,i,j; LL ans; scanf("%d",&T); while(T--){ scanf("%d%d",&n,&m); for(i=0;i<m;i++) scanf("%d%d%d%d%d",&u[i],&v[i],&c[i],&ai[i],&bi[i]); ans=0; Init(); for(i=0;i<m;i++) addedge(u[i],v[i],(LL)(c[i]-bi[i])); ans+=MAX(0ll,bfs()); Init(); for(i=0;i<m;i++) addedge(u[i],v[i],(LL)(c[i]-ai[i])); ans-=MAX(0ll,bfs()); if(ans>0) printf("cnznb!!! %lld ",ans); else if(ans==0) printf("oof!!! "); else printf("rip!!! %lld ",-ans); } return 0; }