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;}

原创粉丝点击