「CodePlus 2017 11 月赛」大吉大利,晚上吃鸡!
n<=50000,m<=50000的图,给s和t,问有多少点对$(a,b)$满足
嗯。
不会。
首先最短路DAG造出来,然后两个条件转述一下:条件一,$N_a$表示从s到t经过a的路径,$N_a+N_b=N_t$;条件二,在最短路DAG上A不能到B,B不能到A。
条件一就迪杰斯特拉的时候算一下N,注意不在最短路DAG上的点$N_i=0$;然后对每个$N_t-N_b$的值存一个bitset,用以表示值为这么多的点的状态,枚举a查多少$N_t-N_b=N_a$即可。
条件二就正反拓扑序跑一下,然后传递闭包算出来即可知道最短路图上哪些点能到a和a能到哪些点,把这些点设为不可达点,取个交集即可算出每个a能和哪些b在条件二下配对。
然后就没了。
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<stdlib.h>
#include<bitset>
#include<queue>
#include<math.h>
//#include<time.h>
//#include<iostream>
using namespace std; int n,m,s,t;
#define maxn 50011
#define maxm 100011
#define LL long long struct Edge{int to,next,v;};
struct qnode
{
int id; LL v;
bool operator < (const qnode &b) const {return v<b.v;}
bool operator > (const qnode &b) const {return v>b.v;}
};
struct Graph
{
Edge edge[maxm<<]; int first[maxn],le;
Graph() {memset(first,,sizeof(first)); le=;}
void in(int x,int y,int v) {Edge &e=edge[le]; e.to=y; e.v=v; e.next=first[x]; first[x]=le++;}
void insert(int x,int y,int v) {in(x,y,v); in(y,x,v);}
priority_queue<qnode,vector<qnode>,greater<qnode> > q;
void dijkstra(int s,LL *dis,LL *f)
{
for (int i=;i<=n;i++) dis[i]=1e18,f[i]=;
dis[s]=; f[s]=;
q.push((qnode){s,});
while (!q.empty())
{
const int now=q.top().id; const LL d=q.top().v; q.pop();
if (d!=dis[now]) continue;
for (int i=first[now];i;i=edge[i].next)
{
const Edge &e=edge[i];
if (dis[e.to]>dis[now]+e.v)
{
dis[e.to]=dis[now]+e.v;
f[e.to]=f[now];
q.push((qnode){e.to,dis[e.to]});
}
else if (dis[e.to]==dis[now]+e.v) f[e.to]+=f[now];
}
}
}
}g; LL dis[][maxn],f[][maxn],val[maxn];
bitset<maxn> where[maxn],can[][maxn];
int indo[maxn],head,tail,que[maxn];
bool check(int x,int y,int v,int ty) {return dis[ty][x]+v+dis[ty^][y]==dis[][t];}
void toposort(int ty)
{
memset(indo,,sizeof(indo));
for (int i=;i<=n;i++)
for (int j=g.first[i];j;j=g.edge[j].next)
{
const Edge &e=g.edge[j];
if (check(i,e.to,e.v,ty)) indo[e.to]++;
}
head=tail=;
for (int i=;i<=n;i++) if (indo[i]==) que[tail++]=i;
while (head!=tail)
{
const int now=que[head++];
for (int i=g.first[now];i;i=g.edge[i].next)
{
const Edge &e=g.edge[i];
if (!check(now,e.to,e.v,ty)) continue;
indo[e.to]--; if (indo[e.to]==) que[tail++]=e.to;
can[ty][e.to]&=can[ty][now];
}
}
} qnode list[maxn];
int main()
{
scanf("%d%d%d%d",&n,&m,&s,&t);
for (int i=,x,y,v;i<=m;i++)
{
scanf("%d%d%d",&x,&y,&v);
g.insert(x,y,v);
}
g.dijkstra(s,dis[],f[]); g.dijkstra(t,dis[],f[]); if (dis[][t]==1e18) {printf("%lld\n",1ll*n*(n-)/); return ;} for (int i=;i<=n;i++) can[][i].set(),can[][i].set(),can[][i][i]=can[][i][i]=;
toposort(); toposort(); for (int i=;i<=n;i++) if (dis[][i]+dis[][i]!=dis[][t]) val[i]=; else val[i]=f[][i]*f[][i];
for (int i=;i<=n;i++) list[i]=((qnode){i,val[i]});
sort(list+,list++n);
list[n+].v=1e18;
for (int i=,j=;i<=n+;i++) if (list[i].v!=list[i-].v)
{
int now=j;
for (;j<i;j++) where[now][list[j].id]=;
} LL ans=;
for (int i=;i<=n;i++)
{
int L=,R=n+; LL tmp=f[][t]-val[i];
while (L<R)
{
int mid=(L+R)>>;
if (list[mid].v>=tmp) R=mid;
else L=mid+;
}
if (L!=n+) ans+=(where[L]&can[][i]&can[][i]).count();
}
printf("%lld\n",ans/);
return ;
}
「CodePlus 2017 11 月赛」大吉大利,晚上吃鸡!的更多相关文章
- 「CodePlus 2017 11 月赛」大吉大利,晚上吃鸡!(dij+bitset)
从S出发跑dij,从T出发跑dij,顺便最短路计数. 令$F(x)$为$S$到$T$最短路经过$x$的方案数,显然这个是可以用$S$到$x$的方案数乘$T$到$x$的方案数来得到. 然后第一个条件就变 ...
- LOJ6252. 「CodePlus 2017 11 月赛」大吉大利,晚上吃鸡! 最短路+bitset
题目传送门 https://loj.ac/problem/6252 https://lydsy.com/JudgeOnline/problem.php?id=5109 题解 首先跑最短路,只保留 \( ...
- loj #6250. 「CodePlus 2017 11 月赛」找爸爸
#6250. 「CodePlus 2017 11 月赛」找爸爸 题目描述 小 A 最近一直在找自己的爸爸,用什么办法呢,就是 DNA 比对. 小 A 有一套自己的 DNA 序列比较方法,其最终目标是最 ...
- [LOJ 6249]「CodePlus 2017 11 月赛」汀博尔
Description 有 n 棵树,初始时每棵树的高度为 H_i,第 i 棵树每月都会长高 A_i.现在有个木料长度总量为 S 的订单,客户要求每块木料的长度不能小于 L,而且木料必须是整棵树(即不 ...
- [LOJ 6248]「CodePlus 2017 11 月赛」晨跑
Description “无体育,不清华”.“每天锻炼一小时,健康工作五十年,幸福生活一辈子” 在清华,体育运动绝对是同学们生活中不可或缺的一部分.为了响应学校的号召,模范好学生王队长决定坚持晨跑.不 ...
- 「CodePlus 2017 11 月赛」Yazid 的新生舞会(树状数组/线段树)
学习了新姿势..(一直看不懂大爷的代码卡了好久T T 首先数字范围那么小可以考虑枚举众数来计算答案,设当前枚举到$x$,$s_i$为前$i$个数中$x$的出现次数,则满足$2*s_r-r > 2 ...
- 「CodePlus 2017 11 月赛」可做题
这种题先二进制拆位,显然改的位置只有每一段确定的数的开头和结尾,只需要对于每一个可决策位置都尝试一下填1和0,然后取min即可. #include<iostream> #include&l ...
- 「CodePlus 2017 11 月赛」Yazid 的新生舞会
n<=500000的数字,问有多少个区间的众数出现次数严格大于区间长度的一半. 这么说来一个区间就一个众数了,所以第一反应是枚举数字,对下标进行处理.然后没有第二反应.很好. 在枚举一个数字的时 ...
- [LOJ#6259]「CodePlus 2017 12 月赛」白金元首与独舞
[LOJ#6259]「CodePlus 2017 12 月赛」白金元首与独舞 试题描述 到河北省 见斯大林 / 在月光下 你的背影 / 让我们一起跳舞吧 うそだよ~ 河北省怎么可能有 Stalin. ...
随机推荐
- VMware虚拟机中涉及的3种常见网络模式
桥接模式.这种模式下,虚拟机和物理机连的是同一个网络,虚拟机和物理机是并列关系,地位是相当的.比如你家如果有用路由器,那么你的电脑和你的手机同时连接这个路由器提供的Wi-Fi,那么它们的关系就是这种模 ...
- 完美单例宏定义(兼容ARC和MRC),项目中可以直接使用
单例模式: 1.永远只分配一块内存来创建对象 2.提供一个类方法, 返回内部唯一的一个对象(一个实例) 3.最好保证init方法也只初始化一次 写一个宏定义文件,传入宏定义函数名,自动生成符合类名的 ...
- [POJ1509]Glass Beads 后缀自动机 最小循环串
题目链接:http://poj.org/problem?id=1509 题目意思就是求循环字符串的最小表示. 我们用字符串S+S建立SAM,然后从root开始走n步,每次尽量选最小的. 由于 SAM ...
- 2017-11-29 HTML5样式、链接和表格
HTML5样式.链接和表格HTML5列表<ol> 有序列表<ul> 无序列表<li> 列表项 <dl> 列表<dt> 列表项<dd&g ...
- R in action读书笔记(9)-第八章:回归 -回归诊断
8.3回归诊断 > fit<-lm(weight~height,data=women) > par(mfrow=c(2,2)) > plot(fit) 为理解这些图形,我们来回 ...
- Swift protocol extension method is called instead of method implemented in subclass
Swift protocol extension method is called instead of method implemented in subclass protocol MyProto ...
- Java入门第39课——猜字母游戏之实现字母生成方法
问题 实现猜字母游戏中的字母生成方法,即,随机生成5个不同的字母作为猜测的结果. 方案 实现generate方法,首先声明一个字符类型的数组,用于存储26个大写字母,然后声 ...
- TYPE=MyISAM 与 ENGINE=MyISAM 的区别(摘要版)
TYPE=MyISAM 和 ENGINE=MyISAM 都是设置数据库存储引擎的语句 (老版本的MySQL使用TYPE而不是ENGINE(例如,TYPE = MYISAM). MySQL 5.1为向下 ...
- 花括号的使用 printf %${width}s , 否则会 去找 $widths
花括号的使用 printf %${width}s , 否则会 去找 $widths 1 #! /usr/bin/perl 2 use strict; 3 use warnings; 4 ...
- 第1节 MapReduce入门:11、mapreduce程序的入门-2
1.5.WordCount示例编写 1.JobMain.java类 package cn.itcast.wordcount; import org.apache.hadoop.conf.Configu ...