903. 昂贵的聘礼

建图方式非常像P1194 买礼物,感觉点权都可以转化到虚拟源点到各个点的边权上。

若不考虑等级关系

  • 等价于求虚拟源点到\(1\)号点的最短路。

若考虑等级关系

  • 考虑枚举。因为必定和酋长交易,那么整个交换过程可取的就是酋长的等级-m到酋长的等级+m。并且每次交易方案中,最小与最大的等级差不超过m。所以可以枚举酋长等级-m到酋长等级的数做左区间,这个数字加上m做右区间,在跑最短路时判断下是否满足条件,最后取答案最小值即可。
const int N=110;
int val[N],level[N];
vector<PII> g[N];
int dist[N];
bool vis[N];
int n,m;

int dijkstra(int l,int r)//从虚拟源点0到1的最短路
{
    memset(dist,0x3f,sizeof dist);
    memset(vis,0,sizeof vis);
    priority_queue<PII,vector<PII>,greater<PII> > heap;
    dist[0]=0;
    heap.push({0,0});

    while(heap.size())
    {
        int t=heap.top().second;
        heap.pop();

        if(vis[t]) continue;
        vis[t]=true;

        for(int i=0;i<g[t].size();i++)
        {
            int j=g[t][i].fi,w=g[t][i].se;
            if(level[j] > r || level[j] < l) continue;
            if(dist[j] > dist[t] + w)
            {
                dist[j]=dist[t]+w;
                heap.push({dist[j],j});
            }
        }
    }
    return dist[1];
}

int main()
{
    cin>>m>>n;

    for(int i=1;i<=n;i++)
    {
        int p;
        cin>>val[i]>>level[i]>>p;
        g[0].push_back({i,val[i]});
        while(p--)
        {
            int x,w;
            cin>>x>>w;
            g[x].push_back({i,w});
        }
    }

    int res=INF;
    for(int i=level[1]-m;i<=level[1];i++)
        res=min(res,dijkstra(i,i+m));
    cout<<res<<endl;

    //system("pause");
}
posted @ 2020-09-26 20:31  Dazzling!  阅读(109)  评论(0编辑  收藏  举报