题意:个城市,条单向路,每一条路从到,如果之前已经经过了城市,花费可以为也可以为,没有经过城市,花费为,求从城市到的最小花费
思路:求最短路,多加一维表示已经走过的点的集合。
#include <stdio.h>
#include <string.h>
#include <queue>
#include <algorithm>
const int INF = 0x3f3f3f3f;
using namespace std;
struct Edge
{
int to,Next,c,a,b;
}edge[205];
struct Node
{
int u,dis,S;
Node(){}
Node(int _u,int _dis,int _S) {
u = _u;
dis = _dis;
S = _S;
}
bool operator<(const struct Node& oth) const {
return dis > oth.dis;
}
};
int dis[11][1 << 11];
bool vis[11][1 << 11];
int tot,head[25],n,m;
void init()
{
tot = 0;
memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int c,int a,int b)
{
edge[tot].to = v;
edge[tot].c = c;
edge[tot].a = a;
edge[tot].b = b;
edge[tot].Next = head[u];
head[u] = tot++;
}
void dijkstra(int s)
{
int i,to;
struct Node t;
memset(dis,INF,sizeof(dis));
memset(vis,false,sizeof(vis));
priority_queue<Node> pq;
pq.push(Node(s,0,1 << s));
dis[0][1 << 0] = 0;
while(!pq.empty()) {
t = pq.top();
pq.pop();
if(vis[t.u][t.S]) continue;
vis[t.u][t.S] = true;
for(i = head[t.u]; i != -1; i = edge[i].Next) {
to = edge[i].to;
if(t.S & (1 << edge[i].c)) {
if(dis[to][t.S | (1 << to)] > dis[t.u][t.S] + edge[i].b) {
dis[to][t.S | (1 << to)] = dis[t.u][t.S] + min(edge[i].a,edge[i].b);
pq.push(Node(to,dis[to][t.S | (1 << to)],t.S | (1 << to)));
}
else if(dis[to][t.S | (1 << to)] > dis[t.u][t.S] + edge[i].a) {
dis[to][t.S | (1 << to)] = dis[t.u][t.S] + min(edge[i].a,edge[i].b);
pq.push(Node(to,dis[to][t.S | (1 << to)],t.S | (1 << to)));
}
}
else {
if(dis[to][t.S | (1 << to)] > dis[t.u][t.S] + edge[i].b) {
dis[to][t.S | (1 << to)] = dis[t.u][t.S] + edge[i].b;
pq.push(Node(to,dis[to][t.S | (1 << to)],t.S | (1 << to)));
}
}
}
}
}
int main(void)
{
int i,u,v,c,a,b,ans;
init();
scanf("%d %d",&n,&m);
for(i = 0; i < m; i++) {
scanf("%d %d %d %d %d",&u,&v,&c,&a,&b);
u--;
v--;
c--;
addedge(u,v,c,a,b);
}
dijkstra(0);
ans = INF;
for(i = 0; i < (1 << n); i++) {
ans = min(ans,dis[n - 1][i]);
}
if(ans == INF)
printf("impossible\n");
else
printf("%d\n",ans);
return 0;
}