#include<iostream>
#include<algorithm>
#include<string.h>
#include<vector>
#include<queue>
using namespace std;
//两个状态压缩很好的解决了重复走路的问题
struct Edge
{
int point,weight;
Edge(int a,int b):point(a),weight(b){}
bool operator>(const Edge&a)const
{
return weight>a.weight;
}
};
vector<Edge>edge[1300];
struct node
{
int a,b,c,p,r;
}a[15];
int dist[10300];
int V;
int N,m;
int main()
{
while(cin>>N>>m)
{
int i;
V=(1<<N)-1;
for(i=0;i<m;i++)
{
cin>>a[i].a>>a[i].b>>a[i].c>>a[i].p>>a[i].r;
for(int s=0;s<=V;s++)
{
if(s&(1<<a[i].c-1))
{
edge[s+(a[i].a-1)*V].push_back(Edge((s|(1<<a[i].c-1))+(a[i].b-1)*V,a[i].p));
}
else
{
edge[s+(a[i].a-1)*V].push_back(Edge((s|(1<<a[i].c-1))+(a[i].b-1)*V,a[i].r));
}
}
}
memset(dist,0x3f3f3f3f,sizeof(dist));
dist[1]=0;
priority_queue<Edge,vector<Edge>,greater<Edge>>sa;
sa.push(Edge(1,0));
while(!sa.empty())
{
//cout<<"1"<<endl;
Edge temp=sa.top();
sa.pop();
if(dist[temp.point]<temp.weight)continue;
// cout<<"2"<<endl;
//cout<<temp.point<<" "<<temp.weight<<endl;
int i;
for(i=0;i<edge[temp.point].size();i++)
{
//cout<<temp.point<<" "<<edge[temp.point][i].weight<<endl;
if(dist[temp.point]+edge[temp.point][i].weight<dist[(edge[temp.point][i].point)])
{
//cout<<dist[(edge[temp.point][i].point)]<<endl;
dist[(edge[temp.point][i].point)]=(dist[temp.point]+edge[temp.point][i].weight);
//cout<<temp.weight<<" "<<dist[temp.point]<<" "<<dist[edge[temp.point][i].point]<<endl;
sa.push(Edge(edge[temp.point][i].point,dist[edge[temp.point][i].point]));
}
}
}
int ans=0x3f3f3f3f;
for(i=0;i<=V;i++)ans=min(ans,dist[i+(N-1)*V]);
if(ans>=0x3f3f3f3f)cout<<"impossible"<<endl;
else
cout<<ans<<endl;
}
}
poj3411
状压+diji
可以重复走路