题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=2962
方法一:
使用spfa最短路算法,二分查找最大高度。
运行结果:
2962 | 140MS | 612K | 1790 B | C++ |
#include<iostream> #include<cstdio> #include<queue> using namespace std; #define INF (1<<30) #define maxn 1005 struct node { int v,lenth,hight; node *next; }*head[maxn],edge[maxn*maxn]; bool vis[maxn]; int h[maxn],d[maxn]; int r,c; //spfa求高度大于hight的以start为起点的单源最短路径 void spfa(int start,int hight) { for(int i = 1; i <= c; i++) d[i] = INF,vis[i] = false; d[start] = 0; vis[start] = true; queue<int>Q; Q.push(start); while( !Q.empty() ) { int now = Q.front(); Q.pop(); vis[now] = false; for(node *p = head[now] ; p ; p = p->next) { if(p->hight >= hight && d[p->v] >= d[now] + p->lenth) { d[p->v] = d[now] + p->lenth; if(!vis[p->v]) { vis[p->v] = true; Q.push(p->v); } } } } } int main() { int i,num = 1,start,end,hight,lenth,l,r,m; while(~scanf("%d%d",&c,&r) && (r||c)) { for(i = 1; i <= c; i++) head[i] = NULL; node *p = edge; while( r-- ) { scanf("%d%d%d%d",&start,&end,&hight,&lenth); if(hight == -1) hight = INF; p->v = end;p->lenth = lenth;p->hight = hight; p->next = head[start]; head[start] = p++; p->v = start;p->lenth = lenth;p->hight = hight; p->next = head[end]; head[end] = p++; } scanf("%d%d%d",&start,&end,&hight); l = 0; r = hight; int ans = INF; //二分高度, while(l <= r) { m = (l+r)>>1; spfa(start,m); if(d[end] == INF)//高度太大 r = m -1; else { hight = m; l = m + 1; ans = d[end]; } } if(num != 1) printf("\n"); if(ans == INF) printf("Case %d:\ncannot reach destination\n",num++); else printf("Case %d:\nmaximum height = %d\nlength of shortest route = %d\n",num++,hight,ans); } return 0; }
方法二:
采用并查集使用kruskal最小生成树算法求最大生成树的方式找出最大高度,然后使用spfa求单源最短路径
运行结果:
Accepted | 2962 | 390MS | 776K | 1944 B | C++ |
#include<iostream> #include<queue> #include<string> #include<algorithm> using namespace std; const int INF = 1 << 30; const int maxn = 1005; struct Savle { int x,y,h; bool operator<(const struct Savle &a)const { return a.h < h; } }save[maxn*maxn]; struct node { int v,h,l; node *next; }*head[maxn],edge[maxn*maxn]; int r,c,set[maxn],dis[maxn]; bool vis[maxn]; int find(int x) { if(x != set[x]) set[x] = find(set[x]); return set[x]; } void spfa(int start,int hight) { for(int i = 1; i <= r; i++) dis[i] = INF; memset(vis,false,sizeof(vis)); vis[start] = true; dis[start] = 0; queue<int>que; que.push(start); while(!que.empty()) { int now = que.front(); que.pop(); vis[now] = false; for(node *p = head[now]; p ; p = p->next) { if(p->h >= hight && dis[p->v] > dis[now] + p->l) { dis[p->v] = dis[now] + p->l; if( !vis[p->v]) { vis[p->v] = true; que.push(p->v); } } } } } int main() { int i,s,e,l,h,num = 1,k; node *p; while(cin >> r >> c && (r||c)) { for(i = 1; i <= r; i++) head[i] = NULL,set[i] = i; p = edge; k = 0; while( c-- ) { cin >> s >> e >> h >> l; if(h == -1)h = INF; p->v = e;p->h = h; p->l = l; p->next = head[s]; head[s] = p++; p->v = s;p->h = h;p->l = l; p->next = head[e]; head[e] = p++; save[k].x = s,save[k].y = e;save[k++].h = h; } sort(save,save+k); cin >> s >> e >> h; int h1 = -1; for(i = 0; i < k; i++) { set[find(save[i].x)] = find(save[i].y); if(find(s) == find(e)) { h1 = save[i].h; break; } } h = h > h1 ? h1 : h; spfa(s,h); if(num != 1) cout << endl; if(dis[e] == INF || h == -1) printf("Case %d:\ncannot reach destination\n",num++); else printf("Case %d:\nmaximum height = %d\nlength of shortest route = %d\n",num++,h,dis[e]); } return 0; }