题目大意:
给定n个点和m条边,每条边是点i到点j的单向边。当经过这条路前经过了点k,那么在经过这条路时付P的金钱,否则付R的金钱。
求点1到点n的最小花费是多少。
解题思路:
这个题可以用优先队列BFS。按照花费的高低排序。但是在BFS过程中不能当经过某一点时就判断他被访问过以后不再经过了。需要对每个点的访问的次数就行记录。超过这个次数就不再访问。其他的都很简单 。
下面是代码:
#include <stdio.h>
#include <string.h>
#include <queue>
using namespace std;
int head[11];
struct edge1
{
int b,c,p,r,next;
} edge[11];
int n,m,cnt;
int num[11];
struct node
{
int pay,fa;
bool vis[11];
bool operator < (const node &a) const
{
return a.pay<pay;
}
};
void addedge(int a,int b,int c,int p,int r)
{
edge[cnt].b=b;
edge[cnt].c=c;
edge[cnt].p=p;
edge[cnt].r=r;
edge[cnt].next=head[a];
head[a]=cnt++;
}
int main()
{
scanf("%d%d",&n,&m);
int a,b,c,p,r;
memset(head,-1,sizeof(head));
cnt=0;
for(int i=0; i<m; i++)
{
scanf("%d%d%d%d%d",&a,&b,&c,&p,&r);
addedge(a,b,c,p,r);
}
struct node temp,xtemp;
memset(temp.vis,false,sizeof(temp.vis));
memset(num,0,sizeof(num));
temp.vis[1]=true;
num[1]++;
temp.pay=0;
temp.fa=1;
priority_queue <struct node> q;
q.push(temp);
while(!q.empty())
{
temp=q.top();
if(temp.fa==n)break;
q.pop();
if(num[temp.fa]>24)continue;
int p=head[temp.fa];
while(p!=-1)
{
xtemp=temp;
xtemp.vis[edge[p].b]=true;
if(xtemp.vis[edge[p].c])
{
xtemp.pay+=edge[p].p;
}
else xtemp.pay+=edge[p].r;
xtemp.fa=edge[p].b;
num[edge[p].b]++;
q.push(xtemp);
p=edge[p].next;
}
}
if(temp.fa!=n)printf("impossible\n");
else
printf("%d\n",temp.pay);
return 0;
}