bfs+状压——朋也与光玉

朋也与光玉

本来说好了再做一下之前没写起的题的,但是看到队友写了这道题手还是比较痒,于是就写了。
——————————————————————————————————————————

题解:

这道题和之前写的拯救大兵很相似,不同点在于这道题没有任何限制的收集光玉。并且题目中说的不存在环,所以是满足拓扑序的,而且光玉的数量很少,可以使用状压。所以就想到了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;
}
发布了181 篇原创文章 · 获赞 10 · 访问量 5095

猜你喜欢

转载自blog.csdn.net/weixin_42979819/article/details/104125746