「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在条件二下配对。
然后就没了。
1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 #include<stdlib.h> 5 #include<bitset> 6 #include<queue> 7 #include<math.h> 8 //#include<time.h> 9 //#include<iostream> 10 using namespace std; 11 12 int n,m,s,t; 13 #define maxn 50011 14 #define maxm 100011 15 #define LL long long 16 17 struct Edge{int to,next,v;}; 18 struct qnode 19 { 20 int id; LL v; 21 bool operator < (const qnode &b) const {return v<b.v;} 22 bool operator > (const qnode &b) const {return v>b.v;} 23 }; 24 struct Graph 25 { 26 Edge edge[maxm<<1]; int first[maxn],le; 27 Graph() {memset(first,0,sizeof(first)); le=2;} 28 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++;} 29 void insert(int x,int y,int v) {in(x,y,v); in(y,x,v);} 30 priority_queue<qnode,vector<qnode>,greater<qnode> > q; 31 void dijkstra(int s,LL *dis,LL *f) 32 { 33 for (int i=1;i<=n;i++) dis[i]=1e18,f[i]=0; 34 dis[s]=0; f[s]=1; 35 q.push((qnode){s,0}); 36 while (!q.empty()) 37 { 38 const int now=q.top().id; const LL d=q.top().v; q.pop(); 39 if (d!=dis[now]) continue; 40 for (int i=first[now];i;i=edge[i].next) 41 { 42 const Edge &e=edge[i]; 43 if (dis[e.to]>dis[now]+e.v) 44 { 45 dis[e.to]=dis[now]+e.v; 46 f[e.to]=f[now]; 47 q.push((qnode){e.to,dis[e.to]}); 48 } 49 else if (dis[e.to]==dis[now]+e.v) f[e.to]+=f[now]; 50 } 51 } 52 } 53 }g; 54 55 LL dis[2][maxn],f[2][maxn],val[maxn]; 56 bitset<maxn> where[maxn],can[2][maxn]; 57 int indo[maxn],head,tail,que[maxn]; 58 bool check(int x,int y,int v,int ty) {return dis[ty][x]+v+dis[ty^1][y]==dis[0][t];} 59 void toposort(int ty) 60 { 61 memset(indo,0,sizeof(indo)); 62 for (int i=1;i<=n;i++) 63 for (int j=g.first[i];j;j=g.edge[j].next) 64 { 65 const Edge &e=g.edge[j]; 66 if (check(i,e.to,e.v,ty)) indo[e.to]++; 67 } 68 head=tail=0; 69 for (int i=1;i<=n;i++) if (indo[i]==0) que[tail++]=i; 70 while (head!=tail) 71 { 72 const int now=que[head++]; 73 for (int i=g.first[now];i;i=g.edge[i].next) 74 { 75 const Edge &e=g.edge[i]; 76 if (!check(now,e.to,e.v,ty)) continue; 77 indo[e.to]--; if (indo[e.to]==0) que[tail++]=e.to; 78 can[ty][e.to]&=can[ty][now]; 79 } 80 } 81 } 82 83 qnode list[maxn]; 84 int main() 85 { 86 scanf("%d%d%d%d",&n,&m,&s,&t); 87 for (int i=1,x,y,v;i<=m;i++) 88 { 89 scanf("%d%d%d",&x,&y,&v); 90 g.insert(x,y,v); 91 } 92 g.dijkstra(s,dis[0],f[0]); g.dijkstra(t,dis[1],f[1]); 93 94 if (dis[0][t]==1e18) {printf("%lld\n",1ll*n*(n-1)/2); return 0;} 95 96 for (int i=1;i<=n;i++) can[0][i].set(),can[1][i].set(),can[0][i][i]=can[1][i][i]=0; 97 toposort(0); toposort(1); 98 99 for (int i=1;i<=n;i++) if (dis[0][i]+dis[1][i]!=dis[0][t]) val[i]=0; else val[i]=f[0][i]*f[1][i]; 100 for (int i=1;i<=n;i++) list[i]=((qnode){i,val[i]}); 101 sort(list+1,list+1+n); 102 list[n+1].v=1e18; 103 for (int i=2,j=1;i<=n+1;i++) if (list[i].v!=list[i-1].v) 104 { 105 int now=j; 106 for (;j<i;j++) where[now][list[j].id]=1; 107 } 108 109 LL ans=0; 110 for (int i=1;i<=n;i++) 111 { 112 int L=1,R=n+1; LL tmp=f[0][t]-val[i]; 113 while (L<R) 114 { 115 int mid=(L+R)>>1; 116 if (list[mid].v>=tmp) R=mid; 117 else L=mid+1; 118 } 119 if (L!=n+1) ans+=(where[L]&can[0][i]&can[1][i]).count(); 120 } 121 printf("%lld\n",ans/2); 122 return 0; 123 }
View Code
转载于:https://www.cnblogs.com/Blue233333/p/8137311.html
「CodePlus 2017 11 月赛」大吉大利,晚上吃鸡!相关推荐
- 「CodePlus 2017 11 月赛」可做题
题目描述 qmqmqm 希望给 sublinekelzrip 出一道可做题.于是他想到了这么一道题目:给一个长度为n的非负整数序列ai,你需要计算其异或前缀和bi,满足条件b1=a1,bi=b ...
- 「CodePlus 2017 12 月赛」火锅盛宴
n<=100000种食物,给每个食物煮熟时间,有q<=500000个操作:在某时刻插入某个食物:查询熟食中编号最小的并删除之:查询是否有编号为id的食物,如果有查询是否有编号为id的熟食, ...
- [CodePlus 2017 11月赛]晨跑 题解(辗转相除法求GCD)
[CodePlus 2017 11月赛]晨跑 Description "无体育,不清华"."每天锻炼一小时,健康工作五十年,幸福生活一辈子".在清华,体育运动绝 ...
- loj6300 「CodePlus 2018 3 月赛」博弈论与概率统计
link 题意: A和B玩游戏,每轮A赢的概率为p.现在有T组询问,已知A赢了n轮输了m轮,没有平局,赢一局A得分+1,输一局得分-1,问A得分期望值? $n+m,T\leq 2.5\times 10 ...
- @loj - 6353@「CodePlus 2018 4 月赛」组合数问题 2
目录 @description@ @solution@ @accepted code@ @details@ @description@ 请你找到 k 个不同的组合数,使得对于其中任何一个组合数 \(C ...
- 「CodePlus 2018 3 月赛」白金元首与克劳德斯
所有的云在此时没有重叠的面积 所有的云在此时没有重叠的面积 所有的云在此时没有重叠的面积 所有的云在此时没有重叠的面积 所有的云在此时没有重叠的面积 所有的云在此时没有重叠的面积 所有的云在此时没有重 ...
- LOJ6299:「CodePlus 2018 3 月赛」白金元首与克劳德斯 (离散化+前缀和)
题目传送门:https://loj.ac/problem/6299 题目分析:一道不难的题目,然而比赛的时候只有90pts.由于所有克劳德斯(clouds)一开始都不相交,所以答案不是1就是2.用O( ...
- 【LibreOJ】#6299. 「CodePlus 2018 3 月赛」白金元首与克劳德斯
[题意]给出坐标系中n个矩形,类型1的矩形每单位时间向x轴正方向移动1个单位,类型2的矩形向y轴正方向,初始矩形不重叠,一个点被矩形覆盖当且仅当它在矩形内部(不含边界),求$(-\infty ,+\i ...
- 【线段树】「CodePlus 2018 3 月赛」白金元首与克劳德斯
题意: 分析: 题意好鬼扯... 非常傻逼的线段树动态开点题. 横向移动的矩形和纵向移动的矩形,看起来非常麻烦. 由于速度均相等,所以可以以所有纵向移动的矩形为参考系,那么所有纵向移动的矩形都是相对静 ...
- 如何在「绝地求生」里成功吃鸡?
作者:AngryAlan 全文共 6753 字 45 图,阅读需要 16 分钟 ---- / BEGIN / ---- 增长黑客(Growth hacking)是一套来自美国硅谷的创业法则,核心是数据 ...
最新文章
- HTML的标签描述13
- 阿里云服务器 Windows连接不成功 提示“你的凭证不工作” 解决方法
- Spring(AbstractRoutingDataSource)实现动态数据源切换--转载
- ArcGIS Server安装的几个问题
- cvs配电保护断路器_电工电器(三)-配电电器-断路器类-剩余电流保护断路器
- mysql_crud
- Accept-Encoding
- 19岁「黑客」连续破解25辆特斯拉
- linux重新设定分区大小
- 公司行政的未来在哪里?要不要转行?
- python、MongoDB安装
- 深信服(SCSA)认证学习—基础知识点二
- 航天信息金税盘接口 js 调用
- linux如何查看python的版本_Python基础知识:如何检查 Python 版本
- ubuntu20.04WPS解决缺失字体的问题
- 消防水池液位报警装置设置参数
- 电脑键盘上的Alt键的作用
- vue中前端实现pdf预览(含vue-pdf插件用法)
- 服务器修改mysql登录密码忘了怎么办,云服务器mysql密码重置密码忘记了
- 6亿视频号的8种变现模式
热门文章
- leetcode 155. Min Stack最小栈(中等)
- 游戏数据库 mysql_网络游戏_数据库查询
- 游戏数据库 TcaplusDB
- 安安静静学JAVA(七)
- 欧美html真人游戏,推荐几个好玩场面大的,欧美3d史诗级rpg魔幻手游
- FineCMS 5.0.10漏洞集合
- 计算机打音乐歌谱成都,赵雷成都的曲谱
- 计算机应用与基础教学计划,计算机应用基础教学计划完整版.docx
- <<视觉问答>>2021:How Transferable are Reasoning Patterns in VQA?
- 人工神经网络指标是什么,人工神经网络指标分析