- Quiz
- AC
- 解説
- その他
- 最初は再帰関数&メモ化で書いたが、その後上記解説を読み、配るDPで書き直した
- 始点に戻ってこれるかどうかをうまく判定することが重要
struct Edge{
ll to;
ll cost;
Edge(ll to, ll cost): to(to), cost(cost) {}
Edge(){
to = 0;
cost = 0;
}
};
int main(){
cin.tie(0);
ios::sync_with_stdio(false);
ll N,M;
cin>>N>>M;
vector<vector<Edge>> G(N);
rep(i,M){
ll a,b,c;
cin>>a>>b>>c;
G[a].push_back({b,c});
}
VV dp(1<<N, VI(N, inf));
auto reset_dp = [&](){
rep(i,1<<N){
rep(j,N){
dp[i][j]=inf;
}
}
};
ll mi=inf;
rep(start,N){
reset_dp();
dp[0][start]=0;
rep(flags,1<<N){
rep(lst,N){
if(dp[flags][lst]==inf)continue;
for(auto edge : G[lst]){
ll to = edge.to;
if((flags>>to&1)==0){
ll new_flags = flags | (1<<to);
ll new_dist = dp[flags][lst] + edge.cost;
chmin(dp[new_flags][to], new_dist);
}
}
}
}
ll all = (1<<N)-1;
if(dp[all][start]==inf)continue;
chmin(mi,dp[all][start]);
}
if(mi==inf){
p(-1);
}else{
p(mi);
}
return 0;
}