大概做法是这样的

考虑最朴素的做法,预处理出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. 解决webstorm卡顿问题

    webstorm强大的功能就不多做介绍了.但是它的缺点也显而易见:吃内存. 电脑配置稍低一点,运行webstorm就特别容易卡顿,特别是项目比较大的时候,那卡顿得不要不要的. 在我的笔记本8g内存 2 ...

  2. 【编程篇】C++11系列之——临时对象分析

    /*C++中返回一个对象时的实现及传说中的右值——临时对象*/ 如下代码: /**********************************************/ class CStuden ...

  3. 实现倒计时功能js

    <p>系统将会在<strong id="endtime"></strong>秒后跳转到登录页!</p> [原生js实现] <s ...

  4. SpringMVC中使用Interceptor拦截器

    SpringMVC 中的Interceptor 拦截器也是相当重要和相当有用的,它的主要作用是拦截用户的请求并进行相应的处理.比如通过它来进行权限验证,或者是来判断用户是否登陆,或者是像12306 那 ...

  5. MongoDB基本使用

    成功启动MongoDB后,再打开一个命令行窗口输入mongo,就可以进行数据库的一些操作. 输入help可以看到基本操作命令: show dbs:显示数据库列表 show collections:显示 ...

  6. 使用JQuery UI selectmenu, onchange事件失效

    今天, 在用jQuery UI的一套东西是发现<select class="dropmenu" onchange="do();"></sele ...

  7. chart.js 里添加图表的清单:

    chart.js 里添加图表的清单: var legend = myDoughnut.generateLegend(); $("#chart_legend").html(legen ...

  8. EasyTouch绑定事件在电脑上点击有效Android上无效的解决方法

    最近做一个RPG类的游戏发现使用EasyTouch虚拟摇杆插件在电脑上点击有效Android上无效,查找资料发现是Easy Joystick中的一个属性interaction type要设置成 Dir ...

  9. poj2389-Bull Math(大整数乘法)

    一,题意: 大整数乘法模板题二,思路: 1,模拟乘法(注意"逢十进一") 2,倒序输出(注意首位0不输出) 三,步骤: 如:555 x 35 = 19425  5 5 5  5 5 ...

  10. 【7集iCore3基础视频】7-6 Quartus II 13.1安装

    Quartus II 13.1安装:高清源视频:链接:http://pan.baidu.com/s/1csVRMA 密码:lkth 视频勘误:http://pan.baidu.com/s/1mhCIq ...