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]; else return -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; else map[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; }