hdu 5137【最短路】

http://acm.hdu.edu.cn/showproblem.php?pid=5137

题意:n个点(1到n编号) 每两点有相应权值  无向图   问1到n  最小花费多少

会随意删除一个点(不能1点 和 n点)

如果最小花费 是不存在 即inf  那就输出Inf

一开始想 最小花费   直接最短路 求dis【n】 会删除点  那就枚举删除的点  在跑dijkstra时 把删除的点跳过  最后每次返回dis【n】

再用ans 保存这些dis【n】 的最小值

后来想了下  并不是保存最小值  而是最大值

因为你想  我随意删除点  他可能删除这个点后  无法从1到n  那dis【n】是inf

如果删除的点不影响  那自然dis【n】就是最短路径

一开始陷入了  把那些能从1到n的方案的最短距离   取其最小值

题目是随意删除点的   如果取了这些方案最短那个  万一删除的点恰好使得这个最短方案  不可行  那答案不就错了 

所以 应该取max   如果ans =inf  说明存在一个删除点方案 会使得无法到达  那不就不可能到达咯

ans!=inf  那不就说明 所有删除点方案  都可行  “最小花费”不就是ans咯 (基于不管你怎么删除 我最小就花这么多)

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<queue>
#include<map>
#include<stack>
#include<sstream>
#include<vector>
#include<string>
#include<set>

using namespace std;
//using namespace __gnu_pbds;

#define IOS ios::sync_with_stdio(false); cin.tie(0);
#define REP(i,n) for(int i=0;i<n;++i)

int read(){

    int r=0,f=1;char p=getchar();
    while(p>'9'||p<'0'){if(p=='-')f=-1;p=getchar();}
    while(p>='0'&&p<='9'){r=r*10+p-48;p=getchar();}return r*f;
}

//typedef tree<pair<long long,int>,null_type,less< pair<long long,int> >,rb_tree_tag,tree_order_statistics_node_update> rbtree;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<long long,long long> pll;
const int Maxn = 5e4+10;
const long long LINF = 1e18;
const int INF = 0x3f3f3f3f;
const int Mod = 10001;
const double PI = acos(-1.0);

int G[40][40], dis[40];
bool used[40];

int Dij (int s, int n, int p) {
	for (int i = 1; i <= n; ++i) {
		dis[i] = INF;
		used[i] = false;
	}
	dis[s] = 0, used[p] = 1;//起始点 删除点 标记已经用过  
	while (1) {
		int v = -1;
		//找还没用过的  第一个没用过 v = u   然后还有没用过的就 找离顶点集 最短那个 
		for (int u = 1; u <= n; ++u) {
			if (!used[u] && (v == -1 || dis[u] < dis[v])) v = u;
		}
		//说明所有点都加入顶点集 
		if (v == -1) break;
		used[v] = true; 
		for (int u = 1; u <= n; ++u) {
			if (u == p) continue;//没必要对删除的点松弛 
			dis[u] = min (dis[u], dis[v]+G[u][v]);
		}
	}
	return dis[n];
}

int main (void)
{
   	int N, M;
   	while (scanf ("%d%d", &N, &M) != EOF) {
   		if (!N && !M) break;
		int u, v, w;
		//图的初始化  自己到自己的距离 0  其余都是inf 
		for (int i = 1; i <= N; ++i) {
			for (int j =1; j <= N; ++j) {
				if (i == j) G[i][j] = 0;
				else G[i][j] = INF;
			}
		}
		for (int i = 0; i < M; ++i) {
			scanf ("%d%d%d", &u, &v, &w);
			//去重   无向图 
			if (G[u][v] > w)
				G[u][v] = G[v][u] = w;
		}
		int ans = 0;
		//枚举删除的点 【2,n-1】 
		for (int i = 2; i < N; ++i) {
			ans = max (ans, Dij (1, N, i));
		}
		if (ans == INF) printf ("Inf\n");
		else printf ("%d\n", ans);
	}
    return 0;
}

猜你喜欢

转载自blog.csdn.net/liangnimahanwei/article/details/82960670