这个题用Spfa就好,dist[i][j]表示当前在点i,状态为j(用二进制表示已经走了哪些城市)的最短路是多少。然后跑Spfa就行了。
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
using namespace std;
const int inf=1<<29;
const int maxn=1<<10;
const int maxm=11;
int n,m,dp[maxm][maxn];
int e,pnt[maxm],nxt[maxm],head[maxm],city[maxm],cost1[maxm],cost2[maxm],dist[maxm][maxn];
bool vis[maxm];
queue<int> q;
void Init()
{
for(int i=0;i<=n;i++)
for(int j=0;j<(1<<n);j++)
dp[i][j]=inf;
}
void AddEdge(int u,int v,int ci,int c1,int c2)
{
pnt[e]=v;nxt[e]=head[u];city[e]=ci;cost1[e]=c1;cost2[e]=c2;head[u]=e++;
}
int Spfa(int st)
{
for(int i=0;i<=n;i++)
for(int j=0;j<(1<<n);j++)
dist[i][j]=inf;
dist[st][0]=0;
q.push(st);
while(!q.empty())
{
int u=q.front();
vis[u]=0;
q.pop();
for(int i=head[u];i!=-1;i=nxt[i])
for(int j=0;j<(1<<n);j++)
{
if(dist[pnt[i]][j|(1<<(pnt[i]-1))]>dist[u][j]+((j&(1<<(city[i]-1)))>0?cost1[i]:cost2[i]))
{
dist[pnt[i]][j|(1<<(pnt[i]-1))]=dist[u][j]+((j&(1<<(city[i]-1)))>0?cost1[i]:cost2[i]);
if(!vis[pnt[i]])
{
q.push(pnt[i]);
vis[pnt[i]]=1;
}
}
}
}
int ans=inf;
for(int i=0;i<(1<<n);i++)
ans=min(ans,dist[n][i]);
return ans;
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
Init();
e=0;
memset(head,-1,sizeof(head));
for(int i=0;i<m;i++)
{
int u,v,city,c1,c2;
scanf("%d%d%d%d%d",&u,&v,&city,&c1,&c2);
AddEdge(u,v,city,c1,c2);
}
int ans=Spfa(1);
if(ans==inf)
printf("impossible\n");
else
printf("%d\n",ans);
}
return 0;
}