题意:N个城市,经过每条边有两种代价,一种是经过了这条边给定的城市,代价为Pi,另一种是直接到对面城市,代价为Ri,求小朋友从1~N的最小代价(注:边是有向的)
题解:
spfa
dis[i][j]表示到i号城市经过了j状态城市的最小代价,直接搞搞傻逼转移就好了
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define ll long long
using namespace std;
const int N = 11;
int n,m,e_num,ans,inf;
int nxt[N*2],to[N*2],h[N],dis[N][1<<N];
bool in[N][1<<N];
struct Edge {int c,a,b;}w[N*2];
struct Node {int x,y;};
queue<Node> q;
void add(int x, int y, int c, int a, int b) {
nxt[++e_num]=h[x],to[e_num]=y,w[e_num]=(Edge){c,a,b},h[x]=e_num;
}
int gi() {
int x=0,o=1; char ch=getchar();
while(ch!='-' && (ch<'0' || ch>'9')) ch=getchar();
if(ch=='-') o=-1,ch=getchar();
while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
return o*x;
}
void spfa() {
memset(dis,63,sizeof(dis));
ans=inf=dis[0][0];
dis[1][1]=0,in[1][1]=0,q.push((Node){1,1});
while(!q.empty()) {
Node u=q.front();
int x=u.x,y=u.y;
in[x][y]=0,q.pop();
for(int i=h[x]; i; i=nxt[i]) {
int v=to[i];
if(y&(1<<(w[i].c-1))) {
if(dis[x][y]+w[i].a<dis[v][y|(1<<(v-1))]) {
dis[v][y|(1<<(v-1))]=dis[x][y]+w[i].a;
if(!in[v][y|(1<<(v-1))]) in[v][y|(1<<(v-1))]=1,q.push((Node){v,y|(1<<(v-1))});
}
}
else {
if(dis[x][y]+w[i].b<dis[v][y|(1<<(v-1))]) {
dis[v][y|(1<<(v-1))]=dis[x][y]+w[i].b;
if(!in[v][y|(1<<(v-1))]) in[v][y|(1<<(v-1))]=1,q.push((Node){v,y|(1<<(v-1))});
}
}
}
}
}
int main() {
while(scanf("%d%d", &n, &m)!=EOF) {
for(int i=1; i<=m; i++) {
int x=gi(),y=gi(),c=gi(),a=gi(),b=gi();
add(x,y,c,a,b);//add(y,x,c,a,b);
}
spfa();
for(int i=1; i<1<<n; i++) {
ans=min(ans,dis[n][i]);
}
if(ans==inf) puts("impossible");
else printf("%d\n", ans);
}
return 0;
}