大概做法是这样的

考虑最朴素的做法,预处理出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. 数论 - Vanya and Computer Game

    Vanya and his friend Vova play a computer game where they need to destroy n monsters to pass a level ...

  2. android4.4源码下载简介

    1. $sudo apt-get install git-core curl2. mkdir ~/bin PATH=~/bin:$PATH3. curl http://commondatastorag ...

  3. 【转】最近公共祖先(LCA)

    基本概念 LCA:树上的最近公共祖先,对于有根树T的两个结点u.v,最近公共祖先LCA(T,u,v)表示一个结点x,满足x是u.v的祖先且x的深度尽可能大. RMQ:区间最小值查询问题.对于长度为n的 ...

  4. jQuery触发a标签点击事件-为什么不跳转

    今天开发发现 使用jQuery触发a标签的点击事件,当前的样式发生了变化,可是没有跳转,为什么? 百度后找到的解决方案: <a onclick="hanle()" href= ...

  5. CI 资源文件加入模板

    CI  资源文件加入模板: (资源文件:图片,css,js ,业务文件csv,txt.....) 1.引入url辅助函数库   helper 2.使用base_url函数  生成文件物理硬盘地址 3. ...

  6. sql例子

    select * from plat_material_resource where stl_url LIKE '/data1/upload%' --截取字符串 UPDATE plat_materia ...

  7. 解决导入so库报错小结

    最近公司准备将重构后的项目上线,可是等到我接手的时候发现一个很纠结的问题:安卓5.0以上的手机(例如我现在在用的红米note3)运行重构后项目发生报错,提示缺少某so库. 而5.0以下的手机(我的小米 ...

  8. JavaScript:Location

    读取.设置url 在url中输入:http://www.cnpiont.com:8090/index.html?user=like&pwd=123#title Console输入: docum ...

  9. redisTemplate的spring配置以及lua脚本驱动

    最近在使用spring-data-redis的redisTemplate,所以写篇使用记录吧. 1.不用多说,使用maven引入相关依赖,因为项目已经引入其他的 <dependency> ...

  10. 下载更新文件后,调用安装器自动安装apk文件

    在更新操作时,下载新apk之后,往往需要自动安装新apk,用以下代码即可安装下载在本地的apk文件(apkFile) Intent intent = new Intent(); intent.setA ...