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;
    }
    
  • 相关阅读:
    word设置的密码忘了怎么办?
    Navicat Report Viewer 设置 HTTP 的方法
    如何处理Navicat Report Viewer 报表
    excel密码忘记了怎么办
    Beyond Compare文本比较搜索功能详解
    Popular Cows POJ
    Problem B. Harvest of Apples HDU
    网络流模型整理
    The Shortest Statement CodeForces
    Vasya and Multisets CodeForces
  • 原文地址:https://www.cnblogs.com/fenghaoran/p/6877892.html
Copyright © 2011-2022 走看看