zoukankan      html  css  js  c++  java
  • 洛谷P1261 服务器储存信息问题

    题目:https://www.luogu.org/problemnew/show/1261

    题目描述

    Byteland王国准备在各服务器间建立大型网络并提供多种服务。

    网络由n台服务器组成,用双向的线连接。两台服务器之间最多只能有一条线直接连接,同时,每台服务器最多只能和10台服务器直接连接,但是任意两台服务器间必然存在一条路径将它们连接在一起。每条传输线都有一个固定传输的速度。δ(V, W)表示服务器V和W之间的最短路径长度,且对任意的V有δ(V, V)=0。

    有些服务器比别的服务器提供更多的服务,它们的重要程度要高一些。我们用r(V)表示服务器V的重要程度(rank)。rank越高的服务器越重要。

    每台服务器都会存储它附近的服务器的信息。当然,不是所有服务器的信息都存,只有感兴趣的服务器信息才会被存储。服务器V对服务器W感兴趣是指,不存在服务器U满足,r(U)>r(W)且δ(V, U)<=δ(V, W)。

    举个例子来说,所有具有最高rank的服务器都会被别的服务器感兴趣。如果V是一台具有最高rank的服务器,由于δ(V, V)=0,所以V只对具有最高rank的服务器感兴趣。我们定义B(V)为V感兴趣的服务器的集合。

    我们希望计算所有服务器储存的信息量,即所有服务器的|B(V)|之和。Byteland王国并不希望存储大量的数据,所以所有服务器存储的数据量(|B(V)|之和)不会超过30n。

    你的任务是写一个程序,读入Byteland王国的网络分布,计算所有服务器存储的数据量。

    输入输出格式

    输入格式:

    第一行两个整数n和m,(1≤n≤30000,1≤m≤5n)。n表示服务器的数量,m表示传输线的数量。

    接下来n行,每行一个整数,第i行的整数为r(i)(1≤r(i)≤10),表示第i台服务器的rank。

    接下来m行,每行表示各条传输线的信息,包含三个整数a,b,t(1≤t≤1000,1≤a,b≤n,a≠b)。a和b是传榆线所连接的两台服务器的编号,t是传输线的长度。

    输出格式:

    一个整数,表示所有服务器存储的数据总量,即|B(V)|之和。

    输入输出样例

    输入样例#1: 复制
    4 3
    2
    3
    1
    1
    1 4 30
    2 3 20
    3 4 20
    输出样例#1: 复制
    9
    

    说明

    输出解释:B(1)={1,2},B(2)={2},B(3)={2,3},B(4)={1,2,3,4}。

    解析

    暴力做法就是n遍spfa,然后按照rank怼一遍就完事了。

    不过能得多少分我就不知道了。。。。。。

    有兴趣的同学可以试一下orz,我就不作了。

    正解当然要对这个求解方案进行优化了啊。

    怎么优化呢?orz

    注意到rank似乎非常小,那就对rank搞点事情。

    一般都能想到记录点x到rank为i的点集的最短路径,但我们为了以后方便可以扩展一下为 x到rank大于等于i的点集的最短路径 ,设为F[i][x]。

    这样每次比较u,v就只要看一看dis(u,v)<F[rank[v]+1][u]。

    我们对他优化一下orz。

    以起点s开始找到一个点v,设v不关心s,则dis(s,v)>=F[rank[s]+1][v];

    若我们尝试把v扔进队列,假设松弛到u,

    则dis(s,u)=dis(s,v)+dis(v,u);

    But dis(s,v)>=F[rank[s]+1][v];

    So dis(s,u)=dis(s,v)+dis(v,u)>=F[rank[s]+1][v]+dis(u,v)>=F[rank[s]+1][u];

    所以此时u也是不对w感兴趣的点,我们还给他扔进去干嘛。。

    答案不超过30n,复杂度不算高。

    这道题告诉我们:spfa到一个不满足条件的点就不要把它扔到队列里面去了嘛。

    (真理:暴力出奇迹)

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cmath>
      4 #include<cstring>
      5 #include<algorithm>
      6 #include<vector>
      7 #include<queue>
      8 using namespace std;
      9 struct node{
     10     int to;
     11     int v;
     12 };
     13 vector<node> edge;
     14 vector<int> G[30010];
     15 vector<int> o_edge[20];
     16 int n,m;
     17 int r[30010];
     18 int u,v,t;
     19 int far[20][30010];
     20 int dis[30010];
     21 bool vis[30010];
     22 bool ok[30010];
     23 int ans;
     24 
     25 void add_edge(int from,int to,int v){
     26     edge.push_back((node){to,v});
     27     edge.push_back((node){from,v});
     28     int m=edge.size();
     29     G[from].push_back(m-2);
     30     G[to].push_back(m-1);
     31 }
     32 
     33 void o_spfa(int x){
     34     memset(vis,false,sizeof(vis));
     35     memset(far[x],0x3f,sizeof(far[x]));
     36     queue<int> q;
     37     for (int i=0;i<o_edge[x].size();++i){
     38         far[x][o_edge[x][i]]=0;
     39         q.push(o_edge[x][i]);
     40     }
     41     while (!q.empty()){
     42         int now=q.front();
     43         q.pop();
     44         vis[now]=false;
     45         for (int i=0;i<G[now].size();++i){
     46             node nxt=edge[G[now][i]];
     47             if (far[x][now]+nxt.v<far[x][nxt.to]){
     48                 far[x][nxt.to]=far[x][now]+nxt.v;
     49                 if (!vis[nxt.to]){
     50                     vis[nxt.to]=true;
     51                     q.push(nxt.to);
     52                 }
     53             }
     54         }
     55     }
     56 }
     57 
     58 void wk(int x){
     59     for (int i=1;i<=n;++i){
     60         if (far[x][i]>far[x+1][i])
     61           far[x][i]=far[x+1][i];
     62     }
     63 }
     64 
     65 void spfa(int x){
     66     memset(vis,false,sizeof(vis));
     67     memset(dis,0x3f,sizeof(dis));
     68     memset(ok,false,sizeof(ok));
     69     dis[x]=0;
     70     vis[x]=1;
     71     queue<int> q; q.push(x);
     72     while (!q.empty()){
     73         int now=q.front();
     74         q.pop();
     75         vis[now]=false;
     76         if (!ok[now]){
     77             ans++;
     78             ok[now]=true;
     79         }
     80         for (int i=0;i<G[now].size();++i){
     81             node nxt=edge[G[now][i]];
     82             if (dis[nxt.to]>dis[now]+nxt.v){
     83                 dis[nxt.to]=dis[now]+nxt.v;
     84                 if (!vis[nxt.to]&&dis[nxt.to]<far[r[x]+1][nxt.to]){
     85                     q.push(nxt.to);
     86                     vis[nxt.to]=true;
     87                 }
     88             }
     89         }
     90     }
     91 }
     92 
     93 int main(){
     94     scanf("%d%d",&n,&m);
     95     for (int i=1;i<=n;++i){
     96         scanf("%d",&r[i]);
     97         o_edge[r[i]].push_back(i);
     98     }
     99     for (int i=1;i<=m;++i){
    100         scanf("%d%d%d",&u,&v,&t);
    101         add_edge(u,v,t);
    102     }
    103     for (int i=1;i<=10;++i) o_spfa(i);    
    104     for (int i=9;i>=1;--i) wk(i); 
    105     for (int i=1;i<=n;++i) spfa(i);
    106     cout<<ans;
    107     return 0;
    108 }
    View Code

    从此你可以向别人炫耀说我用n遍spfa这种大暴力还能a题233

  • 相关阅读:
    tar
    网站后台管理页面
    [转译][马基 杰斯特(MarkeyJester) 摩托罗拉68000 入门教程] 肆
    [转译][马基 杰斯特(MarkeyJester) 摩托罗拉68000 入门教程] 肆
    [转译][马基 杰斯特(MarkeyJester) 摩托罗拉68000 入门教程] 肆
    [转译][马基 杰斯特(MarkeyJester) 摩托罗拉68000 入门教程] 肆
    [转译][马基 杰斯特(MarkeyJester) 摩托罗拉68000 入门教程] 肆
    [转译][马基 杰斯特(MarkeyJester) 摩托罗拉68000 入门教程] 肆
    [转译][马基 杰斯特(MarkeyJester) 摩托罗拉68000 入门教程] 肆
    [转译][马基 杰斯特(MarkeyJester) 摩托罗拉68000 入门教程] 肆
  • 原文地址:https://www.cnblogs.com/gjc1124646822/p/8179567.html
Copyright © 2011-2022 走看看