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