hdu 5361 In Touch 最短路(set+搜索实现)

来源:互联网 发布:fifaol3非i发数据库 编辑:程序博客网 时间:2024/06/05 19:31

题意:leader在1号位置,他要用最小的花费把他的命令通知到位。

   通知方式:每个人可以向离自己[L,R]的距离的人打电话(左右都可以),花费是C

   如题:他花费1可以通知第三四人,三又花费1通知第二个人,第五个人没办法收到

      所以通知五个人的最小花费分别是 0 2 1 1 -1


http://acm.hdu.edu.cn/showproblem.php?pid=5361


分析:

明显的最短路,但是边太多了,所以不能直接建边跑最短路。

用一个set存储所有的点,如果一个点有求得了最小花费,让这个点出set。

因为人固定了,他打电话的花费是固定的,所以可以用类似bfs的思想层次搜索。

第一个人能搜索的人入setF(setF按照花费从小到大排序),每次出set就是出的最小花费的点,根据此点继续进行搜索(在set里面二分找到可以搜的点),搜索到的点入setF。要知道根据这样的搜索方式,先搜索到的点一定已达到最小花费,所以改点直接出set,表示不会继续用它了。

       setF表示要搜索的点(代码中的f),set表示点集(搜完就可以出set了,代码中的st)。

#include<algorithm>#include<iostream>#include<cstdio>#include<cstring>#include<set>#define sf(n)    scanf("%d", &n)#define MT(x,i)  memset(x,i,sizeof(x))typedef long long LL;using namespace std;const int MAXN=2*100005;struct node{    int id; LL dist;    node(int id=-1,LL dist=-1):dist(dist),id(id) {}    bool operator < (const node& rhs) const{ //这个重载< 必须要,让 搜索setF 按照花费从小到大        if(dist==rhs.dist) return id<rhs.id;        return dist<rhs.dist;    }};set<node>f; set<int>st;int L[MAXN],R[MAXN],C[MAXN]; LL ans[MAXN];void add(int start,int en,node cur){    set<int>::iterator s1=st.lower_bound(start);//二分找到可以开始的点    for(; s1!=st.end()&&*s1<=en;){        node y; y.id=*s1; st.erase(s1++); //出点集,以后不再用它        ans[y.id]=cur.dist; //更新最小花费,每个点只会更新这一次        y.dist=cur.dist+C[y.id]; //花费需要加上自己的花费        f.insert(y); //改点入搜索set    }}void solve(){    while(!f.empty()) {        node cur=*f.begin();  f.erase(f.begin());//正在搜索的点        int x=cur.id,start=x+L[x],en=x+R[x];        add(start,en,cur);//搜索左边可以到达的点        start=x-R[x],en=x-L[x];        add(start,en,cur);//搜索右边可以到达的点    }}int main(){    int T,n; sf(T);    while(T--){        sf(n);        for(int i=0; i<n; i++)scanf("%d",&L[i]);        for(int i=0; i<n; i++)scanf("%d",&R[i]);        for(int i=0; i<n; i++)scanf("%d",&C[i]);        f.clear(); st.clear();        for(int i=1; i<n; i++) st.insert(i);        f.insert(node(0,C[0]));//编号,距离        MT(ans,-1); ans[0]=0;        //以上初始化        solve();        for(int i=0; i<n; i++)            printf("%I64d%s",ans[i],i==(n-1)?"\n":" ");    }    return 0;}



0 0
原创粉丝点击