zoukankan      html  css  js  c++  java
  • BZOJ3482 : [COCI2013]hiperprostor

    对于每组询问,spfa求出f[i][j]表示从S出发,经过j条x边到达i的最短路。

    若f[T][i]都为inf,则无解。

    若f[T][0]为inf,则有无穷个解。

    否则可以看作若干条直线,$O(n)$求出凸壳。

    算出相邻两条直线交点横坐标并取下整,若刚好为整数则-1,设b[i]为i与i+1的交点的横坐标。

    则第i(1<=i<t)段的贡献为首项为f(b[i-1]+1),末项为f(b[i])的等差数列。

    最后一段的斜率为0,所以贡献为f[T][0]。

    #include<cstdio>
    typedef long long ll;
    const int N=510,M=10010,inf=~0U>>1;
    int n,m,i,j,x,y,z,S,T,g[N],v[M],w[M],nxt[M],ed,f[N][N],in[N][N],q[1000000][2];
    int h,t,a[N],b[N],cnt;ll sum;
    inline void read(int&a){
      char c;
      while(!((((c=getchar())>='0')&&(c<='9'))||(c=='x')));
      if(c=='x'){a=0;return;}
      a=c-'0';
      while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';
    }
    inline void addedge(int x,int y,int z){v[++ed]=y;w[ed]=z;nxt[ed]=g[x];g[x]=ed;}
    inline void add(int x,int y,int z){
      if(y>=n)return;
      if(f[x][y]<=z)return;
      f[x][y]=z;
      if(!in[x][y])in[x][y]=1,q[++t][0]=x,q[t][1]=y;
    }
    inline double cross(int x,int y){return (double)(f[T][x]-f[T][y])/(double)(y-x);}
    inline int crossi(int x,int y){
      int a=f[T][y]-f[T][x],b=x-y;
      if(a<=0)return 0;
      return(a-1)/b;
    }
    inline void cal(int k,int b,int l,int r){
      if(l<1)l=1;
      if(l>r)return;
      cnt+=r-l+1;
      sum+=((ll)(l+r)*k+2LL*b)*(r-l+1)/2;
    }
    int main(){
      read(n),read(m);
      while(m--)read(x),read(y),read(z),addedge(x,y,z);
      read(m);
      while(m--){
        read(S),read(T);
        for(i=1;i<=n;i++)for(j=0;j<n;j++)f[i][j]=inf;
        h=1,t=0,add(S,0,0);
        while(h<=t){
          x=q[h][0],y=q[h++][1],in[x][y]=0;
          for(i=g[x];i;i=nxt[i])add(v[i],y+(w[i]==0),f[x][y]+w[i]);
        }
        for(j=0;j<n;j++)if(f[T][j]<inf)break;
        if(j==n){puts("0 0");continue;}
        if(f[T][0]==inf){puts("inf");continue;}
        for(t=0,i=n-1;~i;i--)if(f[T][i]<inf){
          while(t>1&&cross(a[t-1],a[t])>=cross(a[t],i))t--;
          a[++t]=i;
        }
        cnt=1,sum=f[T][0];
        for(i=1;i<t;i++)cal(a[i],f[T][a[i]],b[i-1]+1,b[i]=crossi(a[i],a[i+1]));
        printf("%d %lld
    ",cnt,sum);
      }
      return 0;
    }
    

      

  • 相关阅读:
    加密解密
    论事件驱动与异步IO
    linux 基础命令
    libgcc_s_dw2-1.dll 缺失问题解决
    TightVNC 远程桌面
    配置机器学习开发环境(eclipse + anaconda2)
    Caffe 执行python实例并可视化
    Caffe windows编译找不到python27_d.lib问题解决
    PHP 上传文件名中带中文的文件失败问题
    Windows 搭建PHP开发环境
  • 原文地址:https://www.cnblogs.com/clrs97/p/4675155.html
Copyright © 2011-2022 走看看