朋也与光玉
本来说好了再做一下之前没写起的题的,但是看到队友写了这道题手还是比较痒,于是就写了。
——————————————————————————————————————————
题解:
这道题和之前写的拯救大兵很相似,不同点在于这道题没有任何限制的收集光玉。并且题目中说的不存在环,所以是满足拓扑序的,而且光玉的数量很少,可以使用状压。所以就想到了bfs+状压。
因为不知道以哪个点为起点,所以我们直接用超级源点和这些点练了一个权值为0的边。然后就是跑拓扑序DP一下就可以了。
#include <bits/stdc++.h>
//#define int long long
using namespace std;
typedef pair<int,int> pp;
const int N=105,M=1e4+7;
int e[M],ne[M],head[M],w[M],cnt,n,m,K;
int a[N];
const int t=1<<14;
int f[N][t],vis[N][t];
void add(int a,int b,int c)
{
e[cnt]=b,w[cnt]=c,ne[cnt]=head[a],head[a]=cnt++;
}
queue<pp> q;
void bfs(int x)
{
memset(f,0x3f3f3f3f,sizeof f);
f[x][0]=0;
q.push({x,0});
while (!q.empty()){
auto m= (pair<long long int, long long int> &&) q.front(); q.pop();
int u=m.first,state=m.second;
vis[u][state]=0;
for(int i=head[u];~i;i=ne[i]){
int j=e[i];
// cout<<"U : "<<u<<' '<<j<<endl;
if(state&(1<<a[j])) continue;
int tmp=state|(1<<a[j]);
if(f[j][tmp]>f[u][state]+w[i]){
f[j][tmp]=f[u][state]+w[i];
if(!vis[j][tmp]) {
q.push({j, tmp});
vis[j][tmp]=1;
}
}
}
}
}
int main()
{
cin>>n>>m>>K;
memset(head,-1,sizeof head);
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=m;i++){
int a,b,c; cin>>a>>b>>c;
add(a,b,c);
}
for(int i=1;i<=n;i++) add(0,i,0);
bfs(0);
int ans=0x3f3f3f3f;
for(int i=1;i<=n;i++) ans=min(ans,f[i][(1<<K)-1]);
if(ans==0x3f3f3f3f) cout<<"Ushio!"<<endl;
else cout<<ans<<endl;
}