kuangbin 最短路题单 代码

73 篇文章 0 订阅

题单链接
https://vjudge.net/article/752

推荐:4, 5

1. POJ-2387 Til the Cows Come Home

模板题,注意输入是先输入 m 在输入 n

#include <cstdio>
#include <queue>
#include <vector>
#include <cstring>
using namespace std;
#define MAXN 1005


long long n,m;
vector<pair<long long,long long> > graph[MAXN];
long long dis[MAXN];
bool vis[MAXN];

void solve()
{
	scanf("%lld%lld",&m,&n);
	for (long long i=0,u,v,w; i<m; i++) {
		scanf("%lld%lld%lld",&u,&v,&w);
		graph[u].push_back(make_pair(v,w));
		graph[v].push_back(make_pair(u,w));
	}
	
	priority_queue<pair<long long,long long> > Q;
	
	memset(vis,0,sizeof(vis));
	memset(dis,0x7f,sizeof(dis));
	
	Q.push(make_pair(0,1));
	dis[1]=0;

	while (!Q.empty()) {
		long long u=Q.top().second;
		Q.pop();
		
		if (vis[u])
			continue;
		vis[u]=1;
		
		if (u==n) {
			break;
		}
		
		for (long long i=graph[u].size()-1; i>=0; i--) {
			pair<long long,long long> I=graph[u][i];
			long long v=I.first,w=I.second;		
			if (!vis[v] && dis[v]>dis[u]+w) {
				dis[v]=dis[u]+w;
				Q.push(make_pair(-(dis[u]+w),v));
			}
		}
	}
	
	printf("%lld\n",dis[n]);
}

int main()
{
    solve();
    return 0;
}

2. POJ-2253 Frogger

总点个数少,把所有边弄出来,从小到大排个序,一次插入直到起点终点连通,最后插入的就是。(不是并查集嘛……)

#include <cstdio>
#include <algorithm>
#include <vector>
#include <cmath>
using namespace std;

#define MAXN 205

struct edge {
	int u,v;
	double w;
	
	edge(){}
	edge(int uu, int vv, double ww) : u(uu),v(vv),w(ww){}
	
	bool operator<(const edge& B) {return w<B.w;}
};

#define DIS(x,y) (sqrt((X[x]-X[y])*(X[x]-X[y])+(Y[x]-Y[y])*(Y[x]-Y[y])))

int n;
vector<vector<edge> > graph;
vector<edge> E;
double X[MAXN],Y[MAXN];



int f[MAXN];
int Fa(int x) {return f[x]==x ? x : f[x]=Fa(f[x]);}

void solve()
{
	for (int i=0; i<n; i++)
		scanf("%lf%lf",&X[i],&Y[i]);
	
	graph.clear();
	graph.resize(n+2);
	E.clear();
	
	for (int u=0; u<n; u++)
		for (int v=u+1; v<n; v++)
			E.push_back(edge(u,v,DIS(u,v)));

	sort(E.begin(),E.end());
	
	/*
	for (edge e: E) {
		printf("%d %d %f\n",e.u,e.v,e.w);
	}
	*/
	
	for (int i=0; i<n; i++)
		f[i]=i;
	for (int i=0,mi=E.size(); i<mi; i++) {
		int fu=Fa(E[i].u);
		int fv=Fa(E[i].v);
		f[fu]=fv;
		if (Fa(0)==Fa(1)) {
			printf("Frog Distance = %.3f\n",E[i].w);
			return;
		}
	}
	
	
	
	
}

int main()
{
	int ttt=0;
	while (scanf("%d",&n)==1 && n>0) {
		printf("Scenario #%d\n",++ttt);
		solve();
		puts("");
	}
	return 0;
}

3. POJ-1797 Heavy Transportation

和上面那题一样……

#include <cstdio>
#include <algorithm>
using namespace std;
#define MAXN 1005
#define MAXM 2000005

struct edge {
	int u,v,w;
	
	bool operator< (const edge& B) const {return w>B.w;}
	
};

int n,m;
edge E[MAXM];



int f[MAXN];
int Fa(int x) {return f[x]==x ? x : f[x]=Fa(f[x]);}


void solve()
{
	scanf("%d%d",&n,&m);
	
	if (n==1) {
		puts("0\n");
		return;
	}
	
	for (int i=0; i<m; i++)
		scanf("%d%d%d",&E[i].u,&E[i].v,&E[i].w);
	
	sort(E,E+m);
	
	for (int i=1; i<=n; i++)
		f[i]=i;
	
	for (int i=0; i<m; i++) {
		int fu=Fa(E[i].u);
		int fv=Fa(E[i].v);
		f[fu]=fv;
		if (Fa(1)==Fa(n)) {
			printf("%d\n",E[i].w);
			return;
		}
	}
}


int main()
{
	int ttt;
	scanf("%d",&ttt);
	for (int ii=1; ii<=ttt; ii++) {
		printf("Scenario #%d:\n",ii);
		solve();
		puts("");
	}
	return 0;
}

4. POJ-3268 Silver Cow Party

一个点是,他要求有向图中每个(点 p 到固定点 X ,再从 X 回到 P 的最短距离)的最大值,所以过去建一个图,回来建一个图,做两次迪杰斯特拉最短路,把最短路加起来就是最短来回距离了。

#include <cstdio>
#include <vector>
#include <iostream>
#include <queue>
using namespace std;
#define INF (100200000)


void Dij(vector<int> &dis, vector<vector<pair<int,int> > > graph, int n, int X)
{
	vector<bool> vis(n+2);
	priority_queue<pair<int,int> > Q;
	
	for (int i=1; i<=n; i++) {
		vis[i]=0;
		dis[i]=INF;
	}
	dis[X]=0;
	Q.push(make_pair(0,X));
	
	while (Q.size()) {
		int u=Q.top().second;
		Q.pop();
		
		if (vis[u])
			continue;
		vis[u]=1;
		
		for (int i=graph[u].size()-1; i>=0; i--) {
			
			int v=graph[u][i].first;
			int w=graph[u][i].second;
			
			if (!vis[v] && dis[v]>dis[u]+w) {
				dis[v]=dis[u]+w;
				Q.push(make_pair(-dis[v],v));
			}
		}
		
	}
}

int main()
{
	int n,m,X;
	scanf("%d%d%d",&n,&m,&X);
	vector<vector<pair<int,int> > > graph1(n+2);
	vector<vector<pair<int,int> > > graph2(n+2);
	for (int i=0,uu,vv,ww; i<m; i++) {
		scanf("%d%d%d",&uu,&vv,&ww);
		graph1[uu].push_back(make_pair(vv,ww));
		graph2[vv].push_back(make_pair(uu,ww));
	}
	
	
	vector<int> dis1(n+2);
	vector<int> dis2(n+2);
	
	
	Dij(dis1,graph1,n,X);
	Dij(dis2,graph2,n,X);
	
	int ans=0;
	for (int i=1; i<=n; i++)
		ans=max(ans,dis1[i]+dis2[i]);
		
	printf("%d\n",ans);
	return 0;
}

5. POJ-1860 Currency Exchange

SPFA 求正环

#include <cstdio>
#include <vector>
#include <cstring>
#include <queue>
using namespace std;

#define MAXN 105
#define MAXM 105

int N,M,S;
double V;

struct edge {
	int u,v;
	double f,g;
	
	edge(){};
	edge(int uu,int vv,double ff,double gg): u(uu),v(vv),f(ff),g(gg) {}
	
};

vector<edge> graph[MAXN];
double dis[MAXN];
int cnt[MAXN];
bool inqueue[MAXN];


int main()
{
	scanf("%d%d%d%lf",&N,&M,&S,&V);
	for (int i=0; i<M; i++) {
		int a,b;
		double fab,gab,fba,gba;
		scanf("%d%d%lf%lf%lf%lf",&a,&b,&fab,&gab,&fba,&gba);
		graph[a].push_back(edge(a,b,fab,gab));
		graph[b].push_back(edge(b,a,fba,gba));
	}
	
	memset(dis,0,sizeof(dis));
	memset(cnt,0,sizeof(cnt));
	memset(inqueue,0,sizeof(inqueue));
	
	//SPFA
	queue<int> Q;
	Q.push(S);
	inqueue[S]=1;
	dis[S]=V;		//dis 意思是从 S 到这,能拿到的最高钱数 
	cnt[S]=1;
	while (Q.size()) {
		int u=Q.front();
		Q.pop();
		inqueue[u]=0;
		for (int i=graph[u].size()-1; i>=0; i--) {
			int v=graph[u][i].v;
			double f=graph[u][i].f;
			double g=graph[u][i].g;
			double tmp=(dis[u]-g)*f;
			if (tmp>dis[v]) {	//因为 dis 初始值为 0 , 所以不会出现欠钱 
				dis[v]=tmp;
				if (!inqueue[v]) {
					Q.push(v);
					inqueue[v]=1;
					if (++cnt[v]>N) {	//入队次数多于 n 次,说明出现了正环 
						puts("YES");
						return 0;
					}
				}
			}
		}
	}
	
	puts("NO");
	return 0;
}

6.

7. POJ-1502 MPI Maelstrom

Floyd

#include <cstdio>
#define INF 999999999999999ll
#define MAXN 105

int n;
long long d[MAXN][MAXN];


int main()
{
	char str[10];
	
	scanf("%d",&n);
	for (int i=1; i<n; i++) {
		for (int j=0; j<i; j++) {
			if (scanf("%lld",&d[i][j])!=1) {
				scanf("%s",str);
				d[i][j]=d[j][i]=INF;
			}
			else {
				d[j][i]=d[i][j];
			}
		}
	}
	
	for (int i=0; i<n; i++)
		d[i][i]=INF;
	
	for (int k=0; k<n; k++)
		for (int i=0; i<n; i++)
			for (int j=i+1; j<n; j++)
				if (d[i][j]>d[i][k]+d[k][j]) {
					d[i][j]=d[i][k]+d[k][j];
					d[j][i]=d[i][j];
				}
	
	long long ans=0;
	for (int i=0; i<n; i++)
		if (d[0][i]<INF && ans<d[0][i])
			ans=d[0][i];
	
	printf("%lld\n",ans);
	
	return 0;
}

8. POJ-3660 Cow Contest

两个图,求每个点度数再判断一下就行了,数据小,随便做

#include <cstdio>
#include <vector>
#include <cstring>
using namespace std;

vector<int> graph1[110];
vector<int> graph2[110];
bool vis[110];

void dfs(int X, int &cnt, vector<int> *graph)
{
	vis[X]=1;
	for (int i=graph[X].size()-1,v; i>=0; i--) {
		v=graph[X][i];
		if (!vis[v]) {
			cnt++;
			dfs(v,cnt,graph);
		}
	}
}

void solve()
{
	int n,m,ans=0;
	scanf("%d%d",&n,&m);
	
	for (int i=1,a,b; i<=m; i++) {
		scanf("%d%d",&a,&b);
		graph1[a].push_back(b);
		graph2[b].push_back(a);
	}
	
	for (int i=1; i<=n; i++) {
		int cntin=0,cntout=0;
		
		memset(vis,0,sizeof(vis));
		dfs(i,cntin,graph1);
		memset(vis,0,sizeof(vis));
		dfs(i,cntout,graph2);
		
		ans+=(cntin+cntout==n-1);
	}
	printf("%d\n",ans);
}

int main()
{
	solve();
	return 0;
}

9. POJ-2240 Arbitrage

单源最短路即可,令 dis 为最大倍率,看是否有大于一的回路

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值