用mark[i][st]记录到达i点时到所有点情况为st时的最小花费,向下一步走的时候可以查看要到的点需要经过的中间点是否在st中,然后用优先队列+最短路便可以解决了。
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int N=12;
int head[N],nc;
struct edge
{
int to,by,c1,c2,nxt;
}edge[N*3];
void add(int a,int b,int c,int c1,int c2)
{
edge[nc].to=b;edge[nc].nxt=head[a];edge[nc].by=c;edge[nc].c1=c1;edge[nc].c2=c2;head[a]=nc++;
}
struct data
{
int id,cost,state;
bool operator<(const data &next)const
{
return cost>next.cost;
}
data(){}
data(int _id,int _cost,int _state){id=_id;cost=_cost;state=_state;}
};
int mark[N][1<<N];
priority_queue<data> Q;
int dfs(int n)
{
while(!Q.empty())
Q.pop();
memset(mark,-1,sizeof(mark));
Q.push(data(1,0,1));
int ans=-1;
mark[1][1]=0;
while(!Q.empty())
{
data a=Q.top();
Q.pop();
if(a.id==n)
{
if(ans==-1||ans>a.cost)
ans=a.cost;
continue;
}
for(int i=head[a.id];i!=-1;i=edge[i].nxt)
{
int t=edge[i].to;
int st=a.state|(1<<(t-1));
if((1<<(edge[i].by-1))&a.state)
{
if(mark[t][st]==-1||mark[t][st]>a.cost+edge[i].c1)
{
mark[t][st]=a.cost+edge[i].c1;
Q.push(data(t,mark[t][st],st));
}
}
if(mark[t][st]==-1||mark[t][st]>a.cost+edge[i].c2)
{
mark[t][st]=a.cost+edge[i].c2;
Q.push(data(t,mark[t][st],st));
}
}
}
return ans;
}
int main()
{
int n,m;
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(head,-1,sizeof(head));
nc=0;
for(int i=0;i<m;i++)
{
int a,b,c,c1,c2;
scanf("%d%d%d%d%d",&a,&b,&c,&c1,&c2);
add(a,b,c,c1,c2);
}
m=dfs(n);
if(m==-1)
printf("impossible\n");
else
printf("%d\n",m);
}
return 0;
}
浙公网安备 33010602011771号