题意: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 ", ans); } return 0; }