【BZOJ5109】[CodePlus 2017]大吉大利,晚上吃鸡!

Description

最近《绝地求生:大逃杀》风靡全球,皮皮和毛毛也迷上了这款游戏,他们经常组队玩这款游戏。在游戏中,皮皮和毛毛最喜欢做的事情就是堵桥,每每有一个好时机都能收到不少的快递。当然,有些时候并不能堵桥,皮皮和毛毛会选择在其他的必经之路上蹲点。K博士作为一个老年人,外加有心脏病,自然是不能玩这款游戏的,但是这并不能妨碍他对这款游戏进行一些理论分析,比如最近他就对皮皮和毛毛的战士很感兴趣。【题目描述】游戏的地图可以抽象为一张n个点m条无向边的图,节点编号为1到n,每条边具有一个正整数的长度。假定大魔王都会从S点出发到达T点(S和T已知),并且只会走最短路,皮皮和毛毛会在A点和B点埋伏大魔王。
为了保证一定能埋伏到大魔王,同时又想留大魔王一条生路,皮皮和毛毛约定A点和B点必须满足:
1.大魔王所有可能路径中,必定会经过A点和B点中的任意一点
2.大魔王所有可能路径中,不存在一条路径同时经过A点和B点
K博士想知道,满足上面两个条件的A,B点对有多少个,交换A,B的顺序算相同的方案

Input

第一行输入四个整数n,m,S,T(1≤n≤5×10^4,1≤m≤5×10^4,1≤S,T≤n),含义见题目描述。
接下来输入m行,每行输入三个整数u,v,w(1≤u,v≤n,1≤w≤10^9)表示存在一条长度为w的边链接u和v。
1≤n≤5×10^4,1≤m≤5×10^4,1≤w≤10^9

Output

输出一行表示答案

Sample Input

7 7 1 7
1 2 2
2 4 2
4 6 2
6 7 2
1 3 2
3 5 4
5 7 2

Sample Output

6
【样例 1 解释】
合法的方案为 < 2, 3 >, < 2, 4 >, < 4, 3 >, < 4, 5 >, < 6, 3 >, < 6, 5 > 。

题解:第一思路是先随便找出一条最短路,那么最终的A点和B点一定有一个在这条最短路上,我们设在路径上的是A。于是我们枚举所有点B,考虑它可以搭配哪些合法的点A。 不难发现,为了满足条件2,可以选择的点A一定在一段区间中(如果能从B走到A,那么B也一定能走到A后面的点;如果A能走到B,那么A前面的点也一定能走到B),我们可以先求出最短路径图,然后在正图和反图上分别跑拓扑排序+DP,就能得出每个B的合法A区间。

那么条件1如何满足呢?我们可以用拓扑排序求出经过点i的最短路径条数f[i],那么如果A和B满足条件1,等价于f[A]+f[B]=f[T],所以我们可以采用差分的方式,将每个B的f值扔到对应的A区间中,然后枚举所有A,用map维护当前有多少个点的f值等于一个数,每枚举到一个A就查询一下有多少个点的f等于f[T]-f[A]即可。不过f值可能很大,我们可以采用取模的方式,如果感觉还是很虚的话,可以多取几个模数(本人取了两个)。

但是,考试时写了一发只有55分,为什么?45分的数据S和T都不连通,此时要输出$C_n^2$!输出$C_n^2$能得45分也就算了,我后来check了一下数据,发现所有图都是随机的,所有数据中从S到T的最短路最多只有1条!所以呢,本题其实只需要先特判S和T是否连通,若不连通则输出$C_n^2$,否则随便找一条S到T的最短路,设路径上的点数为len,输出len*(n-len)即能得到满分。

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <iostream>
  4. #include <algorithm>
  5. #include <queue>
  6. #include <utility>
  7. #include <map>
  8. #include <vector>
  9. #define mp(A,B) make_pair(A,B)
  10. using namespace std;
  11. typedef long long ll;
  12. const int maxn=50010;
  13. const ll P1=998244353;
  14. const ll P2=1000000007;
  15. int n,m,cnt,len,S,T;
  16. ll ans;
  17. struct node
  18. {
  19. ll x,y;
  20. node() {}
  21. node(ll a,ll b) {x=a,y=b;}
  22. node operator + (const node &a) const {return node((x+a.x)%P1,(y+a.y)%P2);}
  23. node operator * (const node &a) const {return node(x*a.x%P1,y*a.y%P2);}
  24. node operator - (const node &a) const {return node((x-a.x+P1)%P1,(y-a.y+P2)%P2);}
  25. bool operator < (const node &a) const {return (x==a.x)?(y<a.y):(x<a.x);}
  26. }f1[maxn],f2[maxn],f[maxn];
  27. priority_queue<pair<ll,int> > pq;
  28. queue<int> q;
  29. int to[maxn<<1],next[maxn<<1],head[maxn],vis[maxn],d[maxn],pre[maxn],lm[maxn],rm[maxn],p[maxn];
  30. //l正r反
  31. ll val[maxn<<1],s1[maxn],s2[maxn];
  32. map<node,int> s;
  33. vector<node>::iterator it;
  34. vector<node> p1[maxn],p2[maxn];
  35. inline int rd()
  36. {
  37. int ret=0,f=1; char gc=getchar();
  38. while(gc<'0'||gc>'9') {if(gc=='-') f=-f; gc=getchar();}
  39. while(gc>='0'&&gc<='9') ret=ret*10+(gc^'0'),gc=getchar();
  40. return ret*f;
  41. }
  42. inline void add(int a,int b,int c)
  43. {
  44. to[cnt]=b,val[cnt]=c,next[cnt]=head[a],head[a]=cnt++;
  45. }
  46. int main()
  47. {
  48. //freopen("7.in","r",stdin);
  49. n=rd(),m=rd(),S=rd(),T=rd();
  50. int i,j,a,b,c,u,v;
  51. memset(head,-1,sizeof(head)),memset(s1,0x3f,sizeof(s1)),memset(s2,0x3f,sizeof(s2));
  52. for(i=1;i<=m;i++) a=rd(),b=rd(),c=rd(),add(a,b,c),add(b,a,c);
  53. s1[S]=0,pq.push(mp(0,S));
  54. while(!pq.empty())
  55. {
  56. u=pq.top().second,pq.pop();
  57. if(vis[u]) continue;
  58. vis[u]=1;
  59. for(i=head[u];i!=-1;i=next[i]) if(s1[to[i]]>s1[u]+val[i])
  60. s1[to[i]]=s1[u]+val[i],pq.push(mp(-s1[to[i]],to[i]));
  61. }
  62. if(s1[T]==0x3f3f3f3f3f3f3f3fll)
  63. {
  64. printf("%lld",(ll)n*(n-1)/2);
  65. return 0;
  66. }
  67. s2[T]=0,pq.push(mp(0,T)),memset(vis,0,sizeof(vis));
  68. while(!pq.empty())
  69. {
  70. u=pq.top().second,pq.pop();
  71. if(vis[u]) continue;
  72. vis[u]=1;
  73. for(i=head[u];i!=-1;i=next[i]) if(s2[to[i]]>s2[u]+val[i])
  74. s2[to[i]]=s2[u]+val[i],pre[to[i]]=u,pq.push(mp(-s2[to[i]],to[i]));
  75. }
  76. for(i=S;i;i=pre[i]) p[++len]=i,lm[i]=len+1,rm[i]=len-1;
  77. for(i=1;i<=n;i++) if(!lm[i]) lm[i]=1,rm[i]=len;
  78. for(i=1;i<=n;i++) for(j=head[i];j!=-1;j=next[j]) if(val[j]>0&&s1[i]+s2[to[j]]+val[j]==s1[T])
  79. val[j]=-1,val[j^1]=-2,d[to[j]]++;
  80. for(i=1;i<=n;i++) if(!d[i]) q.push(i);
  81. f1[S]=node(1,1),f2[T]=node(1,1);
  82. while(!q.empty())
  83. {
  84. u=q.front(),q.pop();
  85. for(i=head[u];i!=-1;i=next[i]) if(val[i]==-1)
  86. {
  87. v=to[i],d[v]--,f1[v]=f1[v]+f1[u],lm[v]=max(lm[v],lm[u]);
  88. if(!d[v]) q.push(v);
  89. }
  90. }
  91. for(i=1;i<=n;i++) for(j=head[i];j!=-1;j=next[j]) if(val[j]==-2) d[to[j]]++;
  92. for(i=1;i<=n;i++) if(!d[i]) q.push(i);
  93. while(!q.empty())
  94. {
  95. u=q.front(),q.pop();
  96. for(i=head[u];i!=-1;i=next[i]) if(val[i]==-2)
  97. {
  98. v=to[i],d[v]--,f2[v]=f2[v]+f2[u],rm[v]=min(rm[v],rm[u]);
  99. if(!d[v]) q.push(v);
  100. }
  101. }
  102. for(i=1;i<=n;i++)
  103. {
  104. f[i]=f1[i]*f2[i];
  105. if(lm[i]<=rm[i]) p1[lm[i]].push_back(f[i]),p2[rm[i]].push_back(f[i]);
  106. }
  107. for(i=1;i<=len;i++)
  108. {
  109. for(it=p1[i].begin();it!=p1[i].end();it++) s[*it]++;
  110. ans+=s[f[T]-f[p[i]]];
  111. for(it=p2[i].begin();it!=p2[i].end();it++) s[*it]--;
  112. }
  113. printf("%lld",ans);
  114. return 0;
  115. }

【BZOJ5109】[CodePlus 2017]大吉大利,晚上吃鸡! 最短路+拓扑排序+DP的更多相关文章

  1. BZOJ5109 CodePlus 2017大吉大利,晚上吃鸡!(最短路+拓扑排序+bitset)

    首先跑正反两遍dij求由起点/终点到某点的最短路条数,这样条件一就转化为f(S,A)*f(T,A)+f(S,B)*f(T,B)=f(S,T).同时建出最短路DAG,这样图中任何一条S到T的路径都是最短 ...

  2. bzoj5109: [CodePlus 2017]大吉大利,晚上吃鸡!

    Description 最近<绝地求生:大逃杀>风靡全球,皮皮和毛毛也迷上了这款游戏,他们经常组队玩这款游戏.在游戏中,皮皮 和毛毛最喜欢做的事情就是堵桥,每每有一个好时机都能收到不少的快 ...

  3. [BZOJ5109][LOJ #6252][P4061][CodePlus 2017 11月赛]大吉大利,今晚吃鸡!(最短路+拓扑排序+传递闭包+map+bitset(hash+压位))

    5109: [CodePlus 2017]大吉大利,晚上吃鸡! Time Limit: 30 Sec  Memory Limit: 1024 MBSubmit: 107  Solved: 57[Sub ...

  4. [BZOJ5109]大吉大利,晚上吃鸡!

    [BZOJ5109]大吉大利,晚上吃鸡! 题目大意: 一张\(n(n\le5\times10^4)\)个点\(m(m\le5\times10^4)\)条边的无向图,节点编号为\(1\)到\(n\),边 ...

  5. GMA Round 1 大吉大利,晚上吃鸡

    传送门 大吉大利,晚上吃鸡 新年走亲访友能干点啥呢,咱开黑吃鸡吧. 这里有32个人,每个人都可能想玩或者不想玩,这样子一共有$2^{32}$种可能.而要开黑当然得4人4人组一队(四人模式),所以说如果 ...

  6. 「CodePlus 2017 11 月赛」大吉大利,晚上吃鸡!(dij+bitset)

    从S出发跑dij,从T出发跑dij,顺便最短路计数. 令$F(x)$为$S$到$T$最短路经过$x$的方案数,显然这个是可以用$S$到$x$的方案数乘$T$到$x$的方案数来得到. 然后第一个条件就变 ...

  7. 「CodePlus 2017 11 月赛」大吉大利,晚上吃鸡!

    n<=50000,m<=50000的图,给s和t,问有多少点对$(a,b)$满足 嗯. 不会. 首先最短路DAG造出来,然后两个条件转述一下:条件一,$N_a$表示从s到t经过a的路径,$ ...

  8. LOJ6252. 「CodePlus 2017 11 月赛」大吉大利,晚上吃鸡! 最短路+bitset

    题目传送门 https://loj.ac/problem/6252 https://lydsy.com/JudgeOnline/problem.php?id=5109 题解 首先跑最短路,只保留 \( ...

  9. [BZOJ5109/CodePlus2017]大吉大利,晚上吃鸡!

    Description 最近<绝地求生:大逃杀>风靡全球,皮皮和毛毛也迷上了这款游戏,他们经常组队玩这款游戏.在游戏中,皮皮和毛毛最喜欢做的事情就是堵桥,每每有一个好时机都能收到不少的快递 ...

随机推荐

  1. 历届蓝桥杯C/C++省赛试题

    2012年第三届蓝桥杯C/C++程序设计本科B组省赛 2013年第四届蓝桥杯C/C++程序设计本科B组省赛 2014年第五届蓝桥杯C/C++程序设计本科B组省赛 2015年第六届蓝桥杯C/C++程序设 ...

  2. 上手并过渡到PHP7(5)——轻量级“集合”迭代器-Generator

    轻量级“集合”迭代器-Generator泊学视频链接泊阅文档链接Generator是PHP 5.5加入的新语言特性.但是,它似乎并没有被很多PHP开发者广泛采用.因此,在我们了解PHP 7对Gener ...

  3. selenium测试(Java)--元素操作(五)

    元素的操作有 1. 清除文本 2. 模拟按键输入 3. 单击元素 4. 返回元素尺寸 5. 获取文本 6. 获取属性值 7. 判断是否可见 8. 提交 下面通过操作新浪邮箱的注册界面的脚本来展示使用方 ...

  4. python中的高阶函数

    高阶函数英文叫Higher-order function.什么是高阶函数?我们以实际代码为例子,一步一步深入概念. 变量可以指向函数 以Python内置的求绝对值的函数abs()为例,调用该函数用以下 ...

  5. 【转】BMP图像文件格式

    5.1  BMP图像文件格式 BMP图像文件格式是游戏中常用的图像资源文件格式,BMP图像文件起源早,程序员对BMP都比较熟悉,再加上BMP格式简单,读取和写入非常容易实现,所以无论Windows的还 ...

  6. C++ 模板类友元之输出流操作符重载

    几个关键点: 需要前置声明!--奇怪的是别人告诉我也可以不需要,但我这里不行! 友元函数的函数名后面的<>,必须要有. #include <stdio.h> #include ...

  7. 利用CMake和OpenCV源代码生成Visual Studio工程

    OpenCV1.0版本有windows,linux之分,笔者曾经一直使用Opencv1.0.这个版本在下载,安装之后,在 \OpenCV\_make文件夹下面已经存在了一个opencv.dsw的工程文 ...

  8. XML 入门

    XML语法 所有 XML 元素都须有关闭标签 XML 标签对大小写敏感 XML 必须正确地嵌套 XML 文档必须有根元素 就像HTML一样,HTML必须有<html>根元素.XML也必须有 ...

  9. JavaSE(十)之反射

    开始接触的时候可能大家都会很模糊到底什么是反射,大家都以为这个东西不重要,其实很重要的,几乎所有的框架都要用到反射,增加灵活度.到了后面几乎动不动就要用到反射. 首先我们先来认识一下对象 学生---- ...

  10. AssetBundle中Unload()方法的作用

    AssetBundle.Unload(false)的作用: 官网的解释是这样的: When unloadAllLoadedObjects is false, compressed file data ...