解题思路:这题读一遍题目之后,很容易看出这是一个最短路的问题,搭乘一条线路时,收获的钱是得到的钱减去票价,我们自然想要获得的钱越多越好,转化成最短路问题,加个负号就行了,-(得到的钱-票价),票价-得到的钱的意义其实就是付出的钱,自然越少越好。最后最短路的值为负,即得到钱,为正,即付出钱,考虑到有负边,就想到了spfa,但是却T了,重新看题,该题强调 了行程不会形成环,那起点的入度必为0,我们可以用拓扑排序,去边的时候更新dist,这样就只要把图扫一遍了。
注意:这题最后问的都是关于经费的,如果经费负责人到比赛地是赚钱的,那它不会给处女座一分钱,同时处女座到比赛地是赚钱的,他不会花一分经费。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF=0x7f7f7f7f;
const int maxn=2e5+5;
ll dist1[maxn],dist2[maxn];
// 分别是处女座和教练的最短路
ll T,N,M,x,y,z,a,b;
ll in1[maxn],in2[maxn];
// 分别是处女座和教练的入度
struct edge {
ll to;
ll w;
};
vector<edge> t1[maxn],t2[maxn];
void solve() {
memset(dist1,0x7f,sizeof(dist1));
memset(dist2,0x7f,sizeof(dist2));
queue<ll> q1,q2;
dist1[1]=0,dist2[1]=0;
for(int i=1; i<=N; ++i) {
if(!in1[i]) {
q1.push(i);
}
if(!in2[i]) {
q2.push(i);
}
}
ll num1,num2;
while(!q1.empty()) {
int np=q1.front();
q1.pop();
for(int i=0; i<(int)t1[np].size(); ++i) {
edge tp=t1[np][i];
int nto=tp.to,nw=tp.w;
dist1[nto]=min(dist1[nto],dist1[np]+nw);
in1[nto]--;
if(!in1[nto]) {
q1.push(nto);
}
}
}
num1=dist1[N];
while(!q2.empty()) {
int np=q2.front();
q2.pop();
for(int i=0; i<(int)t2[np].size(); ++i) {
edge tp=t2[np][i];
int nto=tp.to,nw=tp.w;
dist2[nto]=min(dist2[nto],dist2[np]+nw);
in2[nto]--;
if(!in2[nto]) {
q2.push(nto);
}
}
}
num2=dist2[N];
if(num2<=0) num2=0;
if(num1<=0) num1=0;
if(num2-num1>0) {
cout<<"cnznb!!!"<<endl;
cout<<num2-num1<<endl;
} else if(num2-num1==0) {
cout<<"oof!!!"<<endl;
} else if(num2-num1<0){
cout<<"rip!!!"<<endl;
cout<<num1-num2<<endl;
}
}
int main() {
std::ios::sync_with_stdio(0);
cin>>T;
while(T--) {
cin>>N>>M;
memset(in1,0,sizeof(in1));
memset(in2,0,sizeof(in2));
for(int i=1;i<=N;++i){
t1[i].clear();
t2[i].clear();
}
for(int i=0; i<M; ++i) {
cin>>x>>y>>z>>a>>b;
t1[x].push_back(edge {y,z-a});
in1[y]++;
t2[x].push_back(edge {y,z-b});
in2[y]++;
}
solve();
}
return 0;
}
T飞了的spfa
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int INF=0x7f7f7f7f;
const int maxn=2e5+5;
int dist[maxn];
int pushnum[maxn];
bool vis[maxn];
struct edge {
int to;
int w;
};
vector<edge> t1[maxn],t2[maxn];
int N,M,T;
int x,y,z,a,b;
bool spfa(int start,vector<edge> tt[maxn]) {
memset(dist,0x7f,sizeof(dist));
memset(vis,false,sizeof(vis));
memset(pushnum,0,sizeof(pushnum));
dist[start]=0;
vis[start]=true;
pushnum[start]++;
queue<int> q;
q.push(start);
while(!q.empty()) {
int p=q.front();
q.pop();
vis[p]=false;
for(int i=0; i<(int)tt[p].size(); ++i) {
edge tmp=tt[p][i];
if(dist[tmp.to]>dist[p]+tmp.w) {
dist[tmp.to]=dist[p]+tmp.w;
if(vis[tmp.to]==false) {
q.push(tmp.to);
vis[tmp.to]=true;
pushnum[tmp.to]++;
if(pushnum[tmp.to]>N) {
return false;
}
}
}
}
}
return true;
}
int main() {
std::ios::sync_with_stdio(0);
cin>>T;
while(T--) {
cin>>N>>M;
for(int i=0; i<M; ++i) {
cin>>x>>y>>z>>a>>b;
t1[x].push_back(edge {y,z-a});
t2[x].push_back(edge {y,z-b});
}
spfa(1,t1);
ll num1=dist[N];
spfa(1,t2);
ll num2=dist[N];
if(num2<=0) num2=0;
if(num2-num1>0){
cout<<"cnznb!!!"<<endl;
cout<<num2-num1<<endl;
}
else if(num2-num1==0){
cout<<"oof!!!"<<endl;
}
else {
cout<<"rip!!!"<<endl;
cout<<num1-num2<<endl;
}
}
return 0;
}