题意:有n个城市,m条路,每条路是双向的,从一个城市到另一个城市,并且有限制通行高度,有路程。
现在有一辆货车,有一个最高货物高度,要从一个城市到一个城市。要保证最高高度情况下,选最短路。
思路:我们可以知道最高高度一定是1到货车高度。所以我们可以二分高度,寻找最高高度,再有dijkstra求最短路。
但是用邻接矩阵会超时,这里可以稍稍剪枝下。怎么剪呢?只要在dijkstra算法里判断达到所求终点,或者没有路走了就退出,不用在多算。
还有一个坑点是输出格式:第一个样例不空行输出答案,而后面要空行再输出答案。而且格式错了居然是 WA!!!
代码:
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #define inf 0x3f3f3f3f using namespace std; struct node{ int v,h; }map[1050][1050]; int n,m,high,maxh,from,to,ansh,ansv,flag; int dis[1050],vis[1050]; void dijktra(int x) { memset(vis,0,sizeof(vis)); vis[from]=1; for(int i=1;i<=n;i++)//不达到高度x的路相当于不通,赋inf即可 { if(map[from][i].h>=x) dis[i]=map[from][i].v; else dis[i]=inf; } for(int i=1;i<n;i++)//dijkstra模板 { int t=inf,p=-1; for(int j=1;j<=n;j++) { if(!vis[j]&&dis[j]<t) { t=dis[j]; p=j; } } vis[p]=1; if(p==to||p==-1)//剪枝 return ; for(int j=1;j<=n;j++) { if(!vis[j]&&dis[j]>map[p][j].v+dis[p]&&map[p][j].h>=x) dis[j]=map[p][j].v+dis[p]; } } } void solve()//二分求高度 { int l=1,r=high; while(l<=r) { int mid=(l+r)/2; dijktra(mid); if(dis[to]!=inf)//mid高度有最短路 { flag=1; ansh=mid; ansv=dis[to]; l=mid+1; } else r=mid-1; } return ; } int main() { int k=1; while(scanf("%d%d",&n,&m)!=EOF) { flag=0; for(int i=1;i<=n;i++)//初始化 { for(int j=1;j<=n;j++) { map[i][j].h=0; map[i][j].v=inf; } } if(!n&&!m) break; int u,v,g,w; for(int i=0;i<m;i++) { scanf("%d%d%d%d",&u,&v,&g,&w); if(g==-1) g=inf;//-1为不限高度 map[u][v].v=map[v][u].v=w; map[u][v].h=map[v][u].h=g; } scanf("%d%d%d",&from,&to,&high); solve(); if(k>1) printf("\n"); printf("Case %d:\n",k++); if(flag) { printf("maximum height = %d\n",ansh); printf("length of shortest route = %d\n",ansv); } else printf("cannot reach destination\n"); } return 0; }