2011年北京大学计算机研究生机试真题(dijkstra+优先队列)
来源:互联网 发布:秦皇岛网络问政平台 编辑:程序博客网 时间:2024/04/30 13:59
http://ac.jobdu.com/problem.php?pid=1162 I Wanna Go Home
方法一:普通的dijkstra
/*很明显的最短路,但关键是如何建图。可以看到,一共只有两种走法,一种是从city1出发,一直走属于group1的city直到city2,或者一直走属于group2的city直到city1。我昨天建了两个图来表示两种情况,分别求最短路,然后取小的,结果越写越乱。今天发现其实一次就可以,只要在建图的时候,如果两个city属于一个group,就建双向图,否则就建从属于group1的city到属于group2的city的单向图。原因很简单,因为两种情况都不会出现从2到1的情况。建好图然后就简单了,注意无解的情况。*/#include<iostream>#include<cstdio>using namespace std;#include<memory.h>int map[601][601],x[601];int dijkstra(int n,int start,int end) //start是原点,n是图中所有点的个数{int visit[601]; //判断是否已存入该点到visit集合中int i,j,k,min,t;for (i=1;i<=n;i++){x[i]=map[start][i];visit[i]=0; //初始都未用过该点}x[start]=0;visit[start]=1;// 依次将未放入visit集合的结点中,取x[]最小值的结点,放入集合visit中// 一旦visit包含了所有顶点,x就记录了从源点到所有其他顶点之间的最短路径长度// 注意是从第二个节点开始,第一个为源点for(i=2;i<=n;i++){min = 16843009;t=-1;// 找出当前未使用的点j的x[j]最小值for(j=1; j<=n; ++j){if(!visit[j] && x[j]<min){t = j; // t保存当前邻接点中距离最小的点的号码min = x[j];}}if(t!=-1){visit[t] = 1; // 将t点存入visit集合中// 更新x的值for(j=1; j<=n; ++j){if (!visit[j] && min+map[t][j]<x[j])x[j]=min+map[t][j];}}}if(x[end]<16843009)return x[end];elsereturn -1;}int main(void){int i,j,n,m,from,to,cost,group[601];while(scanf("%d",&n),n){scanf("%d",&m);for(i=1;i<=n;i++){for(j=1;j<=n;j++){if(i==j)map[i][j]=0;elsemap[i][j]=16843009;}}//memset(map,1,sizeof(map));for(i=0;i<m;i++){scanf("%d %d %d",&from,&to,&cost);if(cost<map[from][to])map[from][to]=map[to][from]=cost;}for(i=1;i<=n;i++)scanf("%d",&group[i]);for(i=1;i<n;i++){for(j=i+1;j<=n;j++){if(group[i]==group[j]) //如果是一个group,不用管continue;else if(group[i]==1 && group[j]==2) //如果一个是1一个是2,则建单向边 map[j][i]=16843009;else if(group[i]==2 && group[j]==1) //如果一个是1一个是2,则建单向边 map[i][j]=16843009;}}printf("%d\n",dijkstra(n,1,2));}return 0;}
方法二:优先队列+邻接表 来实现dijkstra算法
/*优先队列+邻接表 来实现dijkstra算法根据下面的那个模板来修改过来的*/#include<iostream>#include<cstdio>#include<queue>using namespace std;#include<memory.h>#define INF 16843009#define MAXN 601 //结点的个数typedef struct Edge{ int adj; struct Edge *next; int cost;}Edge,*pEdge;Edge edge[MAXN];typedef struct Heap{ bool operator <(Heap T)const { return T.dis<dis; } int x; int dis;}Heap;struct Node{int from,to,cost;}node[10001];void insert_adjlist(int a,int b, int c) //创建邻接表{ pEdge p,q; p=&edge[a]; while(p->next!=NULL) p=p->next; q=new Edge; q->adj=b; q->next=NULL; q->cost=c; p->next=q; }int dijkstra(int n,int start,int end) //start是原点,n是图中所有点的个数{int i,x[MAXN];bool visit[MAXN];Heap cur,in;pEdge p;memset(visit,false,sizeof(visit));for(i=1;i<=n;i++)x[i]=INF;priority_queue< Heap >q; //优先级队列cur.x=start;cur.dis=0;x[start]=0;q.push(cur);while(!q.empty()){cur = q.top();q.pop();if(cur.x == end) //找到终点return cur.dis;if(visit[cur.x]) //访问过continue;visit[cur.x]=true;p=edge[cur.x].next;while(p!=NULL){if(!visit[p->adj]){in.x=p->adj;in.dis=cur.dis+p->cost;if(in.dis<x[in.x]){x[in.x]=in.dis;q.push(in);}}p=p->next;}}return -1;}int main(void){int i,j,n,m,from,to,group[601];while(scanf("%d",&n),n){scanf("%d",&m);for(i=1;i<=n;i++)edge[i].next=NULL;for(i=0;i<m;i++){scanf("%d %d %d",&node[i].from,&node[i].to,&node[i].cost); //暂时保存起来}for(i=1;i<=n;i++)scanf("%d",&group[i]);for(i=0;i<m;i++){from=node[i].from;to=node[i].to;if(group[from]==group[to]) //如果是一个group,建立双向边{insert_adjlist(from,to,node[i].cost);insert_adjlist(to,from,node[i].cost); }else if(group[from]==1 && group[to]==2) //如果一个是1一个是2,则建单向边insert_adjlist(from,to,node[i].cost);else if(group[from]==2 && group[to]==1) //如果一个是1一个是2,则建单向边insert_adjlist(to,from,node[i].cost); }printf("%d\n",dijkstra(n,1,2));}return 0;}
http://acm.hdu.edu.cn/showproblem.php?pid=2544 最短路
//优先队列+邻接表 来实现dijkstra算法(模板)#include<iostream>#include<cstdio>#include<queue>using namespace std;#include<memory.h>#define INF 16843009#define MAXN 601 //结点的个数typedef struct Edge{ int adj; struct Edge *next; int cost;}Edge,*pEdge;Edge edge[MAXN];typedef struct Heap{ bool operator <(Heap T)const { return T.dis<dis; } int x; int dis;}Heap;void insert_adjlist(int a,int b, int c) //创建邻接表{ pEdge p,q; p=&edge[a]; while(p->next!=NULL) p=p->next; q=new Edge; q->adj=b; q->next=NULL; q->cost=c; p->next=q; }int dijkstra(int n,int start,int end) //start是原点,n是图中所有点的个数{int i,x[MAXN];bool visit[MAXN];Heap cur,in;pEdge p;memset(visit,false,sizeof(visit));for(i=1;i<=n;i++)x[i]=INF;priority_queue< Heap >q; //优先级队列cur.x=start;cur.dis=0;x[start]=0;q.push(cur);while(!q.empty()){cur = q.top();q.pop();if(cur.x == end)return cur.dis;if(visit[cur.x])continue;visit[cur.x]=true;p=edge[cur.x].next;while(p!=NULL){if(!visit[p->adj]){in.x=p->adj;in.dis=cur.dis+p->cost;if(in.dis<x[in.x]){x[in.x]=in.dis;q.push(in);}}p=p->next;}}return -1;}int main(void){int i,j,n,m,from,to,cost,group[601];while(scanf("%d %d",&n,&m),n+m){for(i=1;i<=n;i++)edge[i].next=NULL;for(i=0;i<m;i++){scanf("%d %d %d",&from,&to,&cost); insert_adjlist(from,to,cost); insert_adjlist(to,from,cost); }printf("%d\n",dijkstra(n,1,n));}return 0;}
- 2011年北京大学计算机研究生机试真题(dijkstra+优先队列)
- 2011年北京大学计算机研究生机试真题(题解)
- 2010年北京大学计算机研究生机试真题
- 题目1144:Freckles(2009年北京大学计算机研究生机试真题)
- 2007年北京大学计算机研究生机试真题 二叉树
- 题目1153:括号匹配问题(2010年北京大学计算机研究生机试真题,堆栈的使用)
- 题目1118:数制转换(2008年北京大学图形实验室计算机研究生机试真题)
- 题目1112:拦截导弹(2007年北京大学计算机研究生机试真题:动态规划)
- 2011年上海交通大学计算机研究生机试真题
- 2011年吉林大学计算机研究生机试真题
- 2011年上海交通大学计算机研究生机试真题
- 2011年吉林大学计算机研究生机试真题
- Is It A Tree?,判断是否是一棵树。(题目来源:九度OJ 1481,2012年北京大学计算机研究生机试真题)
- 2011年浙江大学计算机及软件工程研究生机试真题
- 2011年哈尔滨工业大学计算机研究生机试真题
- 2011年浙江大学计算机及软件工程研究生机试真题
- 2011年哈尔滨工业大学计算机研究生机试真题
- 2006年上海交通大学计算机研究生机试真题
- Android得到控件在屏幕中的坐标
- Source Insight 3 打开代码后日文注释都是乱码后怎么办
- 程序开始前的准备工作
- Iterator迭代器
- google开放的一些接口
- 2011年北京大学计算机研究生机试真题(dijkstra+优先队列)
- POJ 1236 Network of Schools tarjan强连通缩点
- sql2000安装时,挂起的问题。
- Matrix类中的getColVector问题
- strcm--wcscmp
- 喝水时刻表
- 29、Failure Groups in ASM
- Android应用开发之短信窃听器(补充)
- Gridview用法大总结(牛年珍藏版)