Campus

题目链接
题意:
在樱花季节,WHU(一个有n个节点和m条边的无向图)吸引了大量游客,给管理带来了困扰。每个节点初始时有ai名游客,其中有k个节点是校门,这些校门有自己的开放时间区间[li, ri]。假设存在一个“魔法按钮”,按下后所有游客会以光速从最近的开放校门离开校园。要求计算从第1时刻到第T时刻,每时刻离开校园的所有游客所走过的距离总和。若某个时刻有任何游客无法离开,则该时刻的距离总和视为-1。
思路:
很显然的一个思路,处理出每一个门到各个节点的最短路,在一个时刻中,每个节点的人都从开的那些门中选一个路径最短的门离去。有T个时刻,最暴力的方法肯定不行,我们可以预处理每一个时刻对应的门状态。最后注意一下大门全部关闭的时刻输出-1即可。

点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long
#define ll long long 
const int N = 1e5+5;
int a[N];
int p[20],l[20],r[20];
struct edge{
    int next,vi,wi;
    edge(){}
    edge(int _next,int _vi,int _wi){
        next=_next,vi=_vi,wi=_wi;
    }
}e[N<<1];
int head[N],index;
void insert(int a,int b,int c){
    e[index]=edge(head[a],b,c);
    head[a]=index++;
}
bool vis[N];
map<int,vector<int>>mp; //mp映射不同状态的最短路
void dj(int u){ //以u为起点跑一个最短路
    memset(vis,0,sizeof(vis));
    vector<int>v(N,0x7fffffffffffffff);
    mp[u]=v;
    mp[u][u]=0;
    set<pair<int,int>>s;
    s.insert({0,u});
    while(!s.empty()){
        int dingdian=(*s.begin()).second;
        s.erase(s.begin());
        if(vis[dingdian]) continue;
        vis[dingdian]=1;
        for(int j=head[dingdian];~j;j=e[j].next){
            int v=e[j].vi;
            int w=e[j].wi;
            if(!vis[v]&&mp[u][v]>mp[u][dingdian]+w){
                mp[u][v]=mp[u][dingdian]+w;
                s.insert({mp[u][v],v});
            }
        }
    }
}
map<vector<int>,vector<int>>t; //以门的状态映射时刻
int ans[N];
void solve(){
    memset(head,-1,sizeof(head));
    index=0;
    int n,m,k,T;
    cin>>n>>m>>k>>T;
    for(int i=1;i<=n;++i){
        cin>>a[i];
    }
    for(int i=1;i<=k;++i){
        cin>>p[i]>>l[i]>>r[i];
    }
    for(int i=1;i<=m;++i){
        int u,v,w;
        cin>>u>>v>>w;
        insert(u,v,w);
        insert(v,u,w);
    }
    for(int i=1;i<=k;++i){
        dj(p[i]);
    }
    for(int i=1;i<=T;++i){
        vector<int>v;
        for(int j=1;j<=k;++j){
            if(i>=l[j]&&i<=r[j]){
                v.push_back(p[j]);
            }
        }
        t[v].push_back(i);
    }
    for(auto i=t.begin();i!=t.end();++i){
        vector<int>v=i->first;
        int cnt=0;
        int len=v.size();
        if(len==0){
            cnt=-1;
        }else{
            for(int j=1;j<=n;++j){
                int zuixiao=0x7fffffffffffffff;
                for(int h=0;h<len;++h){
                    zuixiao=min(zuixiao,mp[v[h]][j]); //找最近的门
                }
                cnt+=zuixiao*a[j];
            }
        }
        for(int j=0;j<i->second.size();++j){
            ans[i->second[j]]=cnt;
        }
    }
    for(int i=1;i<=T;++i){
        cout<<ans[i]<<endl;
    }
}
signed main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int _=1;
    // cin>>_;
    while(_--)
    solve();
    return 0;
}
posted @ 2025-02-21 15:57  sjgigj  阅读(18)  评论(0)    收藏  举报