kuangbin 最短路刷题 (2) DEF

D
在这里插入图片描述

建两遍图就可以了,正向建图 —x---为起点,到任意点的最短路
反向建图,x为终点,任意点到x的最短路

E
在这里插入图片描述

Spfa改一下,判断正环即可,当然,是特定正环 从起点s-----到s,当s再次入队的时候break

int n,m,s;double v;

struct Edge{
	Edge(){
	}
	Edge(int u,int v,double r,double lo):u(u),v(v),r(r),lo(lo){
	}
    int u,v;double r,lo;
};
vector <Edge> eg[N];
double d[N];
bool inq[N];
int cnt[N];

double con(double m,double ra,double lo){
return (m-lo)*ra;}

bool spfa(){
//	For(i,0,N)d[i]=0;
	queue<PDI>q;
	q.push({v,s});
	d[s]=v;//inq=1;
	

	
   while(!q.empty()){
        PDI now = q.front();
        q.pop();
		
        int u = now.second;
        inq[u]=0;
        for(int i=0;i<eg[u].size();i++){
            int v = eg[u][i].v;
			double r=eg[u][i].r,lo=eg[u][i].lo;
			
		
            double tre=con(d[u],r,lo);
          
			            
            if(d[v]<tre){
                d[v] = tre;
                if(!inq[v]){q.push({d[v], v}); inq[v]=1; if(v==s)break; }
            }
        }
        
        
    }
    
    if(d[s]>v)return 1;
    else return 0;
}


在这里插入图片描述

F

spfa板子题,判断负环

#include <iostream>
#include <cstring>
#include <string>
#include<cstdio>
#include<map>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#define ll long long
#define PII pair<int, int>
#define PDI pair<double,int>
#define _for(i, a, b) for (int i = a; i < b; i++)
#define For(i, a, b) for (int i = a; i <= b; i++)
#define foR(i, b, a) for (int i = b; i >= a; i--)
#define ms(a,b) memset(a, b, sizeof a)
#define gcd(a, b) __gcd(a, b)
#define lcm(a, b) a / gcd(a, b) * b
#define plf(a) printf("%lf\n",a)
#define sc2(a,b) scanf("%d%d",&a,&b)
#define sl2(a,b) scanf("%lf%lf",&a,&b)
#define sc3(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define sc4(a,b,c,d) scanf("%d%d%d%d",&a,&b,&c,&d)
using namespace std;
const int N = 510, inf = 0x3f3f3f3f;
struct Edge {
	int u,v,w;
};
vector <Edge> eg[N];
int d[N];
bool st[N];
int cnt[N];
int n,m,k;

bool spfa() {
	ms(d,0);
	ms(st,0);
	ms(cnt,0);
	queue<int>q;

	For(i,1,n) {
        q.push(i);
        st[i] = true;
    }

	while(!q.empty()) {
		int u = q.front();q.pop();
		st[u]=0;
		_for(i,0,eg[u].size()) {
			int v = eg[u][i].v, w = eg[u][i].w;
			if(d[v]>d[u]+w) {
				d[v] = d[u] + w;

				cnt[v]=cnt[u]+1;

				if(cnt[v]>=n)return 1;

				if(!st[v]) {
					q.push(v);
					st[v]=1;
				}
			}
		}
	}


	return 0;
}


int main() {

	int t;
	cin>>t;
	while(t--) {
		cin>>n>>m>>k;
		ms(eg,0);
		_for(i,0,m) {
			int u,v,w;
			cin>>u>>v>>w;
			eg[u].push_back({u,v,w});
			eg[v].push_back({v,u,w});
		}
		_for(i,0,k) {
			int u,v,w;
			cin>>u>>v>>w;
			eg[u].push_back({u,v,-w});
		}

		if(spfa())cout<<"YES"<<endl;
		else cout<<"NO"<<endl;

	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值