//http://ac.jobdu.com/problem.php?cid=1040&pid=76 #include <stdio.h> #include <vector> using namespace std; struct E //邻接表中链表元素结构体(边) { int next; //直接相邻节点 int c; //该边权值 int cost; }; vector <E> edge[1001]; //vector作邻接链表,结点不超过100 bool mark[1001]; //mark[i]为true时,表示结点i的最短路径长度已经得到,结点i加入集合k int cost[1001]; int dis[1001]; //mark[i]=true时,从1到i的最短路径长度 //mark[i]=false时,从1到k中某点的最短路径长度再加上从该点到i的距离 int main() { int n,m,i,j; int S,T; //起点,终点 while (scanf("%d%d",&n,&m)!=EOF && n!=0 &&m!=0) { for (i=1;i<=n;i++) { edge[i].clear(); //初始化邻接链表 } while (m--) //根据输入边信息,建立邻接表 { int a,b,c,cost; scanf("%d%d%d%d",&a,&b,&c,&cost); E tmp; //新建节点 tmp.c=c; tmp.cost=cost; tmp.next=b; edge[a].push_back(tmp); //将该边加入结点a的边表,作为邻接边 tmp.next=a; edge[b].push_back(tmp); //加入结点b的边表(因为无向图所以加两次) } scanf("%d%d",&S,&T); for (i=1;i<=n;i++) //初始化 { dis[i]=-1; //-1表示不可达 mark[i]=false; //所有节点不属于集合k } dis[S]=0; mark[S]=true; //长度为0,s标志的起点加入集合k int newP=S; for (i=1;i<n;i++) // 循环n-1次,按路径递增顺序确定其他点的最短路径 { for (j=0;j<edge[newP].size();j++) //遍历新加入k的结点的直接相邻边 { int t=edge[newP][j].next; //该边的另一节点 int c=edge[newP][j].c; int co=edge[newP][j].cost; if (mark[t]==true) //另一节点也属于k,跳过 { continue; }
if (dis[t]==-1 || dis[t]>dis[newP]+c ||(dis[t]==dis[newP]+c && cost[t]>cost[newP]+co )) { //不可达, 更短距离, 相同距离下花费更少 dis[t]=dis[newP]+c; cost[t]=cost[newP]+co; } } int min=123123123; //最小值初始化为一个大数 for (j=1;j<=n;j++) //遍历所有节点 { if (mark[j]==true) //若其属于结合k,跳过 { continue; } if (dis[j]==-1) //若该节点仍不可达(肯定不最短),跳过 { continue; } if (dis[j]<min) //依次比较找最短 { min=dis[j]; //暂时保存最短 newP=j; //暂时保存newP最短边的另一结点 } } mark[newP]=true; // 该点加入集合k,dis[newP]表示从1到newP的最短距离 } printf("%d %d\n",dis[T],cost[T]); } return 0; } /* 注意判定条件:距离相同时,再比较选择花费较少的 */
题目77:最短路径问题
最新推荐文章于 2024-04-16 18:15:51 发布