大概做法是这样的

考虑最朴素的做法,预处理出1到所有点的最短路数组dis1和方案数数组cnt1,和预处理出n到所有点的最短路数组dis2和方案数数组出cnt2,然后暴力枚举点对(A,B),如果A和B之间没有连边,那么就可以考虑添加一条正权边,满足这个条件就能添加dis1[A]+dis2[B]+1<=dis1[n],且cnt1[A]*cnt2[B]>=X,由于是要使方案增加,所以将边权设为dis1[n]-(dis1[A]+dis2[B])是最好的,因为可以继承原有的最短路方案数。那么由于(A,B)和(B,A)只算一次,那么第一维枚举到A第二维枚举到B,和第一维枚举到B第二维枚举到A会不会算同一种呢,可以证明这种情况并不会出现重复技计数。

那么考虑优化,枚举点A,点B需满足dis1[A]+dis2[B]+1<=dis1[n],那么可以将dis2进行排序,然后二分出临界范围,然后查询出这个范围内cnt2[B]>=X/cnt[A]的数目,离线的话做法估计挺多的,我代码里用了主席树,最后还需要去掉范围内已经连边的点和自身。时间复杂度O(nlogn)

  代码

 #include<cstdio>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#define mp make_pair
#define pb push_back
#define fi first
#define sc second
using namespace std;
const int N = ;
const int M = ;
const int inf = ;
typedef pair<int,int> P;
priority_queue<P,vector<P>,greater<P> > Q;
int n,m,i,a,b,c,dis[N],cnt[N],dis1[N],cnt1[N],dis2[N],cnt2[N],X;
int id[N],ID[N],Id[N];
vector<P> e[N];
void gao(int x)
{
int i;
for (i=;i<=n;i++)
dis[i]=inf,cnt[i]=;
dis[x]=;
cnt[x]=;
Q.push(mp(,x));
while (!Q.empty())
{
P tmp=Q.top();
Q.pop();
x=tmp.sc;
if (dis[x]!=tmp.fi) continue;
for (i=;i<e[x].size();i++)
if (dis[x]+e[x][i].sc<dis[e[x][i].fi])
{
dis[e[x][i].fi]=dis[x]+e[x][i].sc;
cnt[e[x][i].fi]=cnt[x];
Q.push(mp(dis[e[x][i].fi],e[x][i].fi));
}
else
if (dis[x]+e[x][i].sc==dis[e[x][i].fi])
{
cnt[e[x][i].fi]+=cnt[x];
if (cnt[e[x][i].fi]>X) cnt[e[x][i].fi]=X;
}
}
} int ls[M],rs[M],s[M],tot,root[N];
void build(int &x,int a,int b)
{
x=++tot;
ls[x]=rs[x]=s[x]=;
if (b-a>)
{
int m=(a+b)>>;
build(ls[x],a,m);
build(rs[x],m,b);
}
}
void insert(int y,int &x,int a,int b,int l,int r)
{
x=++tot;
ls[x]=ls[y];rs[x]=rs[y];s[x]=s[y]+;
if ((a<=l)&&(r<=b))
return;
int m=(l+r)>>;
if (a<m) insert(ls[y],ls[x],a,b,l,m);
if (m<b) insert(rs[y],rs[x],a,b,m,r);
}
int query(int x,int a,int b,int l,int r)
{
if ((a<=l)&&(r<=b))
return s[x];
int m=(l+r)>>,ans=;
if (a<m) ans+=query(ls[x],a,b,l,m);
if (m<b) ans+=query(rs[x],a,b,m,r);
return ans;
}
bool cmp(int a,int b)
{
return dis2[a]<dis2[b];
}
bool CMP(int a,int b)
{
return cnt2[a]>cnt2[b];
}
int main()
{
while (~scanf("%d%d",&n,&m))
{
if (n+m==) return ;
for (i=;i<=n;i++) e[i].clear();
scanf("%d",&X);
for (i=;i<=m;i++)
{
scanf("%d%d%d",&a,&b,&c);
e[a].pb(mp(b,c));
e[b].pb(mp(a,c));
}
gao();
for (i=;i<=n;i++)
dis1[i]=dis[i],cnt1[i]=cnt[i];
gao(n);
for (i=;i<=n;i++)
dis2[i]=dis[i],cnt2[i]=cnt[i]; tot=;
build(root[],,n);
for (i=;i<=n;i++)
id[i]=i;
sort(id+,id++n,cmp);
for (i=;i<=n;i++)
ID[id[i]]=i; for (i=;i<=n;i++)
Id[i]=i;
sort(Id+,Id++n,CMP);
for (i=;i<=n;i++)
insert(root[i-],root[i],ID[Id[i]]-,ID[Id[i]],,n);
long long ans=;
for (i=;i<=n;i++)
{
int l=,r=n;
while (l<=r)
{
m=(l+r)>>;
if (dis2[id[m]]+dis1[i]+<=dis1[n]) l=m+;else r=m-;
}
int j=r; l=;r=n;
while (l<=r)
{
m=(l+r)>>;
if (1LL*cnt1[i]*cnt2[Id[m]]>=X) l=m+;else r=m-;
} if (j) ans=ans+query(root[r],,j,,n); for (int k=;k<e[i].size();k++)
if (dis2[e[i][k].fi]++dis1[i]<=dis1[n])
if (1LL*cnt1[i]*cnt2[e[i][k].fi]>=X) ans--; if (dis1[i]+dis2[i]+<=dis1[N])
if (1LL*cnt1[i]*cnt2[i]>=X) ans--; }
printf("%lld\n",ans);
}
}

HDU5870 Alice's Adventure in Wonderland的更多相关文章

  1. the little schemer 笔记(10)

    第十章 What Is  the Value of All of This? entry条目 是由list表组成的 pair 对,pair 对的第一个list表是集合 set.另外,两个list表的长 ...

  2. Comparing the Performance of .NET Serializers(zz)

    The .NET framework comes with a variety of different serializers. Hopefully, my overview of these se ...

  3. zoj Treasure Hunt IV

    Treasure Hunt IV Time Limit: 2 Seconds      Memory Limit: 65536 KB Alice is exploring the wonderland ...

  4. RSA实例破解

    Description: Decode the message. You intercept the following message, which you know has been encode ...

  5. ZOJ3629 Treasure Hunt IV(找到规律,按公式)

    Treasure Hunt IV Time Limit: 2 Seconds      Memory Limit: 65536 KB Alice is exploring the wonderland ...

  6. python抓取数据构建词云

    1.词云图 词云图,也叫文字云,是对文本中出现频率较高的"关键词"予以视觉化的展现,词云图过滤掉大量的低频低质的文本信息,使得浏览者只要一眼扫过文本就可领略文本的主旨. 先看几个词 ...

  7. 生活英语读写MOOC-Literature Tutor-有声名著阅读推荐

    生活英语读写MOOC-Literature Tutor-有声名著阅读推荐 1. Alice's Adventures in Wonderland 爱丽丝漫游奇境记 音频与文本下载地址:链接:http: ...

  8. September 05th 2017 Week 36th Tuesday

    I always in the deepest despair, meet the most beautiful sunrise. 我总是在最深的绝望里遇见最美丽的惊喜. Some pessimist ...

  9. September 04th 2017 Week 36th Monday

    Try not to become a man of success but rather try to become a man of value. 不要努力去做一个成功的人,而要努力去做一个有价值 ...

随机推荐

  1. java基础-泛型2

    浏览以下内容前,请点击并阅读 声明 6 类型推测 java编译器能够检查所有的方法调用和对应的声明来决定类型的实参,即类型推测,类型的推测算法推测满足所有参数的最具体类型,如下例所示: //泛型方法的 ...

  2. Android入门(六):Android控件布局属性全解

    第一类:属性值为true或falseandroid:layout_centerHrizontal 水平居中 (Hrizontal表示水平)android:layout_centerVertical 垂 ...

  3. grunt 一个目录下所有的js文件压缩 配置收藏

    module.exports = function(grunt){ // 项目配置 grunt.initConfig({ pkg: grunt.file.readJSON('package.json' ...

  4. (转)我看PhD by 王珢

    我看PhD by 王垠 前段时间看了一下这些关于 PhD 的负面信息: 一个专门反对读 PhD 的 BLOG 叫“100 Reasons NOT to Go to Graduate School”(下 ...

  5. cookie小析

    cookie用于存储数据,当用户访问了某个网站(网页)时,我们就可以通过cookie来向访问者电脑上存储数据1.不同的浏览器存放的cookie位置不同,也不能通用2.cookie的存储是以域名的形式进 ...

  6. mallmold开源商城系统网银在线chinabank支付插件

    最近没事捣鼓项目,找了个轻型商城系统mallmold,用起来还觉的挺不错的,尤其是mallmold中文版,赞一个.中文版集成了大部分主流支付系统,但因是个人网站,没法获得对应的服务,最终选择了网银在线 ...

  7. 【手把手教你Maven】构建过程

    Maven是一款进行 依赖管理.项目构建.信息管理 为一体的工具. 它不像Make具有复杂的命令.也不像Ant需要手动编写大量的重复代码就能进行项目的构建: 还能提供强大的依赖库管理,避免jar包混乱 ...

  8. Unity3D的四种坐标系

    [Unity3D的四种坐标系] 1.World Space(世界坐标):我们在场景中添加物体(如:Cube),他们都是以世界坐标显示在场景中的.transform.position可以获得该位置坐标. ...

  9. Apache配置过程

    要在一台主机上搭建多个网站,最简单的办法就是给不同的网站分配不一样的端口.下面我以Ubuntu 14.04 + Apache 2.4.7为例说一下在搭建过程中的一些注意事项. 1. 主配置文件是/et ...

  10. 前端开发与SEO

    前端开发中通过一些小习惯,可以有利于SEO,本着蚊子再小也是肉的原则,能抓住自然不能忽略. 1.控制首页链接数量,不能过多,也不要太少.更不要为了凑数而添加 2.扁平化层次,力争跳转三次可以到任何页面 ...