(Nowcoder) 牛客寒假算法基础集训营3 B 处女座的比赛资格 (拓扑排序)

传送门

解题思路:这题读一遍题目之后,很容易看出这是一个最短路的问题,搭乘一条线路时,收获的钱是得到的钱减去票价,我们自然想要获得的钱越多越好,转化成最短路问题,加个负号就行了,-(得到的钱-票价),票价-得到的钱的意义其实就是付出的钱,自然越少越好。最后最短路的值为负,即得到钱,为正,即付出钱,考虑到有负边,就想到了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;
}

猜你喜欢

转载自blog.csdn.net/TDD_Master/article/details/86663750
今日推荐