zoukankan      html  css  js  c++  java
  • 服务器储存信息问题 差分约束

    下面是题面。

    【问题描述】
    
    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 ≤ 30 000 , 1 ≤ m ≤ 5n) 。 n 表示服务器的数量, m 表示传输线的数量。 接下来 n 行,每行一个整数,第 i 行的整数为 r(i)(1 ≤ r(i) ≤ 10) ,表示第 i 台服务器的rank 。 接下来 m 行,每行表示各条传输线的信息,包含三个整数 a , b , t(1 ≤ t ≤ 1000 , l ≤ a , b ≤ n , a ≠ b) 。
    a 和 b 是传输线所连接的两台服务器的编号, t 是传输线的长度。 【输出】 一个整数,表示所有服务器存储的数据总量,即| B(V) |之和。 【样例】 Servers.in 4 3 2 3 1 1 1 4 30 2 3 20 3 4 20 servers . out 9 注: B(1)={1 , 2} , B(2)={2} , B(3)={2 , 3} , B(4)={1 , 2 , 3 , 4} 。

    我们发现暴力很好想也很好写,做n遍SPFA,再按rank把点扫一遍就好了,复杂度大概是平方级的。

    那么正解应该是在这上面的优化。

    注意到最终的答案不会超过30n,但是点对有n^2个?所以说这应该是一个剪枝点。

    同时发现rank<=10?

    有一个非常重要的数据,点x到rank为i的点集的最短路径。有了这个可以方便很多计算,这也是rank很小的原因之一。

    于是我们把它记为 Far[i][x];

    然后我们可以扩展一下它的含义:"x到rank为i的点集的最短路径"可以换成"x到rank大于等于i的点集的最短路径"。

    这样我们一次比较u和v,就只要看一下:far(u,v)<Far[rank[v]+1][u];(far就是δ);

    那么接下来来剪上面那个枝。

    现在我们以w为起点,找到了一个点v,而v不关心w;

    不满足关系的条件为: far(w,v) >= Far[rank[w]+1][v];

    若我们把v扔进队列进行接下来的SPFA松弛,假设v松弛到u;

    由SPFA性质得此时 far(u,w)=far(w,v)+far(v,u);

    而 far(w,v) >= Far[rank[w]+1][v];

    所以 far(w,u)

    =far(u,v)+far(v,w)

    >=far(u,v)+Far[rank[w]+1][v]

    >=Far[rank[w]+1][u];

    所以此时u也是不对w感兴趣的点。

    这告诉我们:SPFA到一个不满足条件的点,你大可不必将它放进队列里。

    因为题目告诉我们答案不超过30n,所以SPFA的复杂度均摊下来很小。

    于是你切完这题后就可以跟别人说:"啊?我做了n遍SPFA就过了啊!"

    听上去似乎有那么点道理... ...

    #include    <iostream>
    #include    <cstdio>
    #include    <cstdlib>
    #include    <algorithm>
    #include    <vector>
    #include    <cstring>
    #include    <queue>
    #define LL long long int
    #define ls (x << 1)
    #define rs (x << 1 | 1)
    #define rank bobo
    using namespace std;
    
    const int N = 30010;
    const int M = N*10;
    struct Data{int to,next;}Edge[N];
    struct Node{int to,val,next;}E[M];
    int n,m,Head[12],Tot,head[N],tot,rank[N];
    int Ans,Far[12][N],far[N],In[N],vis[N];
    
    int gi()
    {
      int x=0,res=1;char ch=getchar();
      while(ch>'9'||ch<'0'){if(ch=='-')res*=-1;ch=getchar();}
      while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
      return x*res;
    }
    
    inline void Link(int u,int v)
    {
      Edge[++Tot]=(Data){v,Head[u]};
      Head[u]=Tot;
    }
    
    inline void link(int u,int v,int c)
    {
      E[++tot]=(Node){v,c,head[u]};
      head[u]=tot;
    }
    
    inline void SPFA1(int p)
    {
      memset(Far[p],127/3,sizeof(Far[p]));
      memset(In,0,sizeof(In));
      queue<int>Q;
      for(int e=Head[p];e;e=Edge[e].next){
        Far[p][Edge[e].to]=0;
        Q.push(Edge[e].to);
      }
      while(!Q.empty()){
        int x=Q.front();Q.pop();In[x]=0;
        for(int e=head[x];e;e=E[e].next){
          int y=E[e].to;
          if(Far[p][x]+E[e].val<Far[p][y]){
    	Far[p][y]=Far[p][x]+E[e].val;
    	if(!In[y])In[y]=1,Q.push(y);
          }
        }
      }
    }
    
    inline void TS(int p)
    {
      for(int x=1;x<=n;++x)
        if(Far[p][x]>Far[p+1][x])
          Far[p][x]=Far[p+1][x];
    }
    
    inline void SPFA(int p)
    {
      memset(far,0x3f,sizeof(far));
      memset(vis,0,sizeof(vis));
      far[p]=0;In[p]=1;  
      queue<int>Q;Q.push(p);
      while(!Q.empty()){
        int x=Q.front();Q.pop();In[x]=0;
        if(!vis[x])Ans+=(vis[x]=1);
        for(int e=head[x];e;e=E[e].next){
          int y=E[e].to;
          if(far[y]>far[x]+E[e].val){
    	far[y]=far[x]+E[e].val;
    	if(!In[y] && far[y]<Far[rank[p]+1][y])
    	  Q.push(y),In[y]=1;
          }
        }
      }
    }
    
    int main()
    {
      n=gi();m=gi();
      for(int i=1;i<=n;++i){
        rank[i]=gi();Link(rank[i],i);
      }
      for(int i=1;i<=m;++i){
        int u=gi(),v=gi(),t=gi();
        link(u,v,t);link(v,u,t);
      }
      for(int i=1;i<=10;++i)SPFA1(i);
      for(int i=9;i;--i)TS(i);
      for(int i=1;i<=n;++i)SPFA(i);
      printf("%d
    ",Ans);
      return 0;
    }
    
  • 相关阅读:
    加密
    读取excel
    poj 1852 Ants
    关于运行时间
    poj 1001 Exponentiation
    Poj 3669 Meteor Shower
    一道简单题目的优化过程——抽签问题
    高精度四则运算
    Usaco_Contest_2013_Open_Bovine Problem 1. Bovine Ballet
    h5 音频 视频全屏设置
  • 原文地址:https://www.cnblogs.com/fenghaoran/p/6877892.html
Copyright © 2011-2022 走看看