算法課複習 -- 圖、Dijkstra

HDU #1874 : 暢通工程續

傳送門:http://acm.hdu.edu.cn/showproblem.php?pid=1874

題意:n個點m條邊的無向圖,給定s和t,問從s到t的最短路。

思路:單源最短路,dijkstra即可。

AC代碼:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<utility>
#include<algorithm>
#include<utility>
#include<queue>
#include<vector>
#include<set>
#include<stack>
#include<cmath>
#include<map>
#include<ctime>
#include<functional>
#include<bitset>
#define P pair<int,int>
#define ll long long
#define ull unsigned long long
#define lson id*2,l,mid
#define rson id*2+1,mid+1,r
#define ls id*2
#define rs (id*2+1)
#define Mod(a,b) a<b?a:a%b+b
#define cl0(a) memset(a,0,sizeof(a))
#define cl1(a) memset(a,-1,sizeof(a))
using namespace std;

const ll M = 1e9 + 7;
const ll INF = 1e18 + 10;
const double _e = 10e-6;
const int maxn = 210;
const int matSize = 9;
const int dx[4] = { 0,0,1,-1 }, dy[4] = { 1,-1,0,0 };
const int _dx[8] = { -1,-1,-1,0,0,1,1,1 }, _dy[8] = { -1,0,1,-1,1,-1,0,1 };

int x, y, z;
char c;

struct node
{
	int id;
	int dis;
};

int n, m, s, t;
vector<node> G[maxn];
int dis[maxn];

struct cmp
{
	bool operator()(node a, node b)
	{
		return a.dis > b.dis;
	}
};

int dij()
{
	priority_queue<node, vector<node>, cmp> que;
	que.push(node{ s,0 }); dis[s] = 0;
	while (!que.empty()) {
		node u = que.top(); que.pop();
		if (u.id == t)
			return u.dis;
		for (int i = 0; i < G[u.id].size(); i++) {
			node v = G[u.id][i];
			if (dis[v.id] == -1 || dis[u.id] + v.dis < dis[v.id]) {
				dis[v.id] = dis[u.id] + v.dis;
				que.push(node{ v.id,dis[v.id] });
			}
		}
	}
	return -1;
}

int main()
{
	while (~scanf("%d%d", &n, &m)) {
		for (int i = 0; i < n; i++)
			G[i].clear();
		cl1(dis);
		while (m--) {
			scanf("%d%d%d", &x, &y, &z);
			G[x].push_back(node{ y,z });
			G[y].push_back(node{ x,z });
		}
		scanf("%d%d", &s, &t);
		int ans = dij();
		printf("%d\n", ans);
	}
	return 0;
}

 

HDU #1596 : find the safest road

傳送門:http://acm.hdu.edu.cn/showproblem.php?pid=1596

題意:有n個城市,給出兩兩間的安全度(0~1之間),問從s到t一路上的安全度之積最大爲多少。

思路:由於0~1之間的數相乘只會變小或相等,因此可以用最短路的方法來求最大安全度之積。對於詢問都做一遍dijkstra即可。

AC代碼:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<utility>
#include<algorithm>
#include<utility>
#include<queue>
#include<vector>
#include<set>
#include<stack>
#include<cmath>
#include<map>
#include<ctime>
#include<functional>
#include<bitset>
#define P pair<int,int>
#define ll long long
#define ull unsigned long long
#define lson id*2,l,mid
#define rson id*2+1,mid+1,r
#define ls id*2
#define rs (id*2+1)
#define Mod(a,b) a<b?a:a%b+b
#define cl0(a) memset(a,0,sizeof(a))
#define cl1(a) memset(a,-1,sizeof(a))
using namespace std;

const ll M = 1e9 + 7;
const ll INF = 1e18 + 10;
const double _e = 10e-6;
const int maxn = 1010;
const int matSize = 9;
const int dx[4] = { 0,0,1,-1 }, dy[4] = { 1,-1,0,0 };
const int _dx[8] = { -1,-1,-1,0,0,1,1,1 }, _dy[8] = { -1,0,1,-1,1,-1,0,1 };

int x, y, z;
char c;

struct node
{
	int id;
	double dis;
};

int n, m;
double cnt[maxn][maxn];
double dis[maxn];

struct cmp
{
	bool operator()(node a, node b)
	{
		return a.dis < b.dis;
	}
};

void dij()
{
	priority_queue<node, vector<node>, cmp> que;
	for (int i = 1; i <= n; i++)
		dis[i] = -1;
	dis[x] = 1; que.push(node{ x, dis[x] });
	while (!que.empty()) {
		node u = que.top(); que.pop();
		if (u.id == y) {
			if (u.dis == 0)
				puts("What a pity!");
			else
				printf("%.3f\n", u.dis);
			return;
		}
		for (int i = 1; i <= n; i++) {
			if (i == u.id)continue;
			if (dis[u.id] * cnt[u.id][i] > dis[i]) {
				dis[i] = dis[u.id] * cnt[u.id][i];
				que.push(node{ i,dis[i] });
			}
		}
	}
}

int main()
{
	while (~scanf("%d", &n)) {
		for (int i = 1; i <= n; i++) {
			for (int j = 1; j <= n; j++)
				scanf("%lf", &cnt[i][j]);
		}
		scanf("%d", &m);
		while (m--) {
			scanf("%d%d", &x, &y);
			dij();
		}
	}
	return 0;
}

 

51Nod #1459 : 迷宮遊戲

傳送門:https://www.51nod.com/Challenge/Problem.html#!#problemId=1459

題意:n個房間m條路,每條路有花費的時間t和獲得的得分s,問在花最短時間的前提下,最高得分爲多少。

思路:單源最短路,不過要多記一個得分。

當第一次走到終點時,記錄當前的時間t並繼續進行搜索並更新得分,直到所需的時間>t時才結束搜索。

AC代碼:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<utility>
#include<algorithm>
#include<utility>
#include<queue>
#include<vector>
#include<set>
#include<stack>
#include<cmath>
#include<map>
#include<ctime>
#include<functional>
#include<bitset>
#define P pair<int,int>
#define ll long long
#define ull unsigned long long
#define lson id*2,l,mid
#define rson id*2+1,mid+1,r
#define ls id*2
#define rs (id*2+1)
#define Mod(a,b) a<b?a:a%b+b
#define cl0(a) memset(a,0,sizeof(a))
#define cl1(a) memset(a,-1,sizeof(a))
using namespace std;

const ll M = 1e9 + 7;
const ll INF = 1e9;
const double _e = 10e-6;
const int maxn = 210;
const int matSize = 9;
const int dx[4] = { 0,0,1,-1 }, dy[4] = { 1,-1,0,0 };
const int _dx[8] = { -1,-1,-1,0,0,1,1,1 }, _dy[8] = { -1,0,1,-1,1,-1,0,1 };

int x, y, z;

struct node
{
	int v;
	int dis;
};

struct node1
{
	int id;
	int score;
	int dis;
};

vector<node> G[510];
int score[510];
int dis[510];
int n, m, start, endd;

int ans_t, ans_s;

struct cmp
{
	bool operator()(node1 a, node1 b)
	{
		return a.dis > b.dis;
	}
};

void dij()
{
	priority_queue<node1, vector<node1>, cmp> que;
	que.push(node1{ start,score[start],0 });
	dis[start] = 0;
	while (!que.empty()) {
		node1 u = que.top(); que.pop();
		if (u.dis > ans_t)return;
		if (u.id == endd) {
			ans_t = min(ans_t, u.dis);
			ans_s = max(ans_s, u.score);
			continue;
		}
		for (int i = 0; i < G[u.id].size(); i++) {
			node v = G[u.id][i];
			if (dis[v.v] == -1 || u.dis + v.dis <= dis[v.v]) {
				dis[v.v] = u.dis + v.dis;
				que.push(node1{ v.v,u.score + score[v.v],u.dis + v.dis });
			}
		}
	}
}

int main()
{
	while (~scanf("%d%d%d%d", &n, &m, &start, &endd)) {
		cl1(dis);ans_s = -1; ans_t = INF;
		for (int i = 0; i < n; i++)
			scanf("%d", &score[i]);
		while (m--) {
			scanf("%d%d%d", &x, &y, &z);
			G[x].push_back(node{ y,z });
			G[y].push_back(node{ x,z });
		}
		dij();
		printf("%d %d\n", ans_t, ans_s);
	}
	return 0;
}

 

POJ #2253 : Frogger

傳送門:http://poj.org/problem?id=2253

題意:給出n個平面座標上的點,問所有從點1到達點2的方法中,過程中的最大距離的最小值爲多少。

思路:單源最短路,但這裏最短的不是總體距離而是每次的距離,所以dis數組記錄的東西改變一下就可以了。

(PE的每個case最後要空行)

AC代碼:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<utility>
#include<algorithm>
#include<utility>
#include<queue>
#include<vector>
#include<set>
#include<stack>
#include<cmath>
#include<map>
#include<ctime>
#include<functional>
#include<bitset>
#define P pair<int,int>
#define ll long long
#define ull unsigned long long
#define lson id*2,l,mid
#define rson id*2+1,mid+1,r
#define ls id*2
#define rs (id*2+1)
#define Mod(a,b) a<b?a:a%b+b
#define cl0(a) memset(a,0,sizeof(a))
#define cl1(a) memset(a,-1,sizeof(a))
using namespace std;

const ll M = 1e9 + 7;
const ll INF = 1e9;
const double _e = 10e-6;
const int maxn = 210;
const int matSize = 9;
const int dx[4] = { 0,0,1,-1 }, dy[4] = { 1,-1,0,0 };
const int _dx[8] = { -1,-1,-1,0,0,1,1,1 }, _dy[8] = { -1,0,1,-1,1,-1,0,1 };

int x, y, z;

struct nn
{
	double x, y;
};

int n;
nn a[maxn];
double dis[maxn];

struct node
{
	int id;
	double dis;
};

struct cmp
{
	bool operator()(node a, node b)
	{
		return a.dis > b.dis;
	}
};

double cal(int aa, int bb)
{
	return sqrt((a[aa].x - a[bb].x)*(a[aa].x - a[bb].x) + (a[aa].y - a[bb].y)*(a[aa].y - a[bb].y));
}

void dij()
{
	priority_queue<node, vector<node>, cmp> que;
	for (int i = 1; i <= n; i++) {
		dis[i] = cal(1, i);
		que.push(node{ i,dis[i] });
	}

	while (!que.empty()) {
		node u = que.top(); que.pop();
		if (u.id == 2) {
			printf("Frog Distance = %.3f\n", u.dis);
			break;
		}
		for (int i = 1; i <= n; i++) {
			if (i == u.id)continue;
			double d = cal(u.id, i);
			d = max(d, u.dis);
			if (d < dis[i]) {
				dis[i] = d;
				que.push(node{ i,dis[i] });
			}
		}
	}
}

int main()
{
	int _ = 1;
	while (~scanf("%d", &n)) {
		if (n == 0)break;
		for (int i = 1; i <= n; i++)
			dis[i] = INF;
		for (int i = 1; i <= n; i++) 
			scanf("%lf%lf", &a[i].x, &a[i].y);
		printf("Scenario #%d\n", _);	
		dij();
		printf("\n");
		_++;
	}
	return 0;
}

 

HDU #2680 : Choose the best route

傳送門:http://acm.hdu.edu.cn/showproblem.php?pid=2680

題意:n個點m條邊的有向圖,給定多個起點和一個終點,問從起點到終點最短距離是多少。

思路:把終點看作起點做dijkstra,取起點中距離最近的點就是答案。

AC代碼:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<utility>
#include<algorithm>
#include<utility>
#include<queue>
#include<vector>
#include<set>
#include<stack>
#include<cmath>
#include<map>
#include<ctime>
#include<functional>
#include<bitset>
#define P pair<int,int>
#define ll long long
#define ull unsigned long long
#define lson id*2,l,mid
#define rson id*2+1,mid+1,r
#define ls id*2
#define rs (id*2+1)
#define Mod(a,b) a<b?a:a%b+b
#define cl0(a) memset(a,0,sizeof(a))
#define cl1(a) memset(a,-1,sizeof(a))
using namespace std;

const ll M = 1e9 + 7;
const ll INF = 1e9 + 10;
const double _e = 10e-6;
const int maxn = 1010;
const int matSize = 9;
const int dx[4] = { 0,0,1,-1 }, dy[4] = { 1,-1,0,0 };
const int _dx[8] = { -1,-1,-1,0,0,1,1,1 }, _dy[8] = { -1,0,1,-1,1,-1,0,1 };

int x, y, z;
char c;

int n, m, endd, w;
vector<int> G[maxn];
int cost[maxn][maxn];
int dis[maxn];

struct node
{
	int id;
	int dis;
};

struct cmp
{
	bool operator()(node a, node b)
	{
		return a.dis > b.dis;
	}
};

void dij()
{
	priority_queue<node, vector<node>, cmp> que;
	que.push(node{ endd,0 }); dis[endd] = 0;
	while (!que.empty()) {
		node u = que.top(); que.pop();
		for (int i = 0; i < G[u.id].size(); i++) {
			int v = G[u.id][i];
			if (dis[v] == -1 || dis[v] > u.dis + cost[u.id][v]) {
				dis[v] = u.dis + cost[u.id][v];
				que.push(node{ v,dis[v] });
			}
		}
	}
}

int main()
{
	while (~scanf("%d%d%d", &n, &m, &endd)) {
		for (int i = 1; i <= n; i++)
			G[i].clear();
		cl1(cost); cl1(dis);
		while (m--) {
			scanf("%d%d%d", &x, &y, &z);
			G[y].push_back(x);
			if (cost[y][x] == -1 || cost[y][x] > z)
				cost[y][x] = z;
		}
		dij(); 
		int ans = INF;
		scanf("%d", &w);
		while (w--) {
			scanf("%d", &x);
			if (dis[x] != -1)
				ans = min(ans, dis[x]);
		}
		if (ans == INF)ans = -1;
		printf("%d\n", ans);
	}
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章