Description

有n个岛屿,m座桥,每座桥连通两座岛屿,桥上会有一些敌人,玩家只有消灭了桥上的敌人才能通过,与此同时桥上的敌人会对玩家造成一定伤害。而且会有一个大Boss镇守一座桥,以玩家目前的能力,是不可能通过的。而Boss是邪恶的,Boss会镇守某一座使得玩家受到最多的伤害才能从岛屿1到达岛屿n(当然玩家会选择伤害最小的路径)。

问,Boss可能镇守桥有哪些。

Input

第一行两个整数n,m

接下来m行,每行三个整数s,t,c,表示一座连接岛屿s和t的桥上的敌人会对玩家造成c的伤害。

1<=n<=100000,1<=m<=200000,1<=c<=10000,数据保证玩家可以从岛屿1到达岛屿n

Output

一行,两个整数d,cnt,d表示有Boss的情况下,玩家要受到的伤害,cnt表示Boss有可能镇守的桥的数目。

Sample Input

3 4

1 2 1

1 2 2

2 3 1

2 3 1

Sample Output

3 1


首先简化题面,问去掉原图的一条边之后,令新图S到T的最短路长度最大的方案数

我们要明白一件事,割的边肯定是最短路径上的边,那么我们就找一条最短路径,考虑经过其他的边的贡献。如果经过其他路径的话,我们一定是走形如\(S\rightarrow A\rightarrow B\rightarrow T\)的形式,并且\(A\rightarrow B\)一定是一条边,是路径我就在其中找一条边出来充当\(A\rightarrow B\)

那么\(A\rightarrow B\)会对哪些点造成贡献呢?首先明白\(S\rightarrow A\)的路线,一定是\(S\rightarrow x\rightarrow A\),其中x是最短路径上的某一个点,那么有贡献的肯定是x到T路径上的点。上界找完了,下界呢?

既然上界是根据S开始走的路线,那么我们反着求一遍最短路,找一个类似的点y满足\(T\rightarrow y\rightarrow B\),那么下界肯定就是y了。

也就是说这条路径形如\(S\rightarrow x\rightarrow A\rightarrow B\rightarrow y\rightarrow T\),因此说明只要\(x\rightarrow y\)之间的某条路径被删了,我们就可以走\(A\rightarrow B\)这条路线,这样我们就可以把走\(A\rightarrow B\)的贡献加到区间\(x\rightarrow y\)中,维护最小值,最后取出所有路径中的最大值统计个数即可

这样弄好之后,我们相当于枚举一条边,在一段区间进行更新,这样我们就可以用线段树来进行维护了

  1. /*program from Wolfycz*/
  2. #include<cmath>
  3. #include<cstdio>
  4. #include<cstring>
  5. #include<iostream>
  6. #include<algorithm>
  7. #define inf 0x7f7f7f7f
  8. using namespace std;
  9. typedef long long ll;
  10. typedef unsigned int ui;
  11. typedef unsigned long long ull;
  12. inline int read(){
  13. int x=0,f=1;char ch=getchar();
  14. for (;ch<'0'||ch>'9';ch=getchar()) if (ch=='-') f=-1;
  15. for (;ch>='0'&&ch<='9';ch=getchar()) x=(x<<1)+(x<<3)+ch-'0';
  16. return x*f;
  17. }
  18. inline void print(int x){
  19. if (x>=10) print(x/10);
  20. putchar(x%10+'0');
  21. }
  22. const int N=1e5,M=2e5;
  23. int pre[(M<<1)+10],now[N+10],child[(M<<1)+10],val[(M<<1)+10];
  24. int dfn[N+10],L[N+10],R[N+10],h[N+10];
  25. bool vis[N+10],In_way[N+10],flag[(M<<1)+10];
  26. int n,m,tot,num,Ans,Max,Dis;
  27. struct S1{
  28. #define ls (p<<1)
  29. #define rs (p<<1|1)
  30. #define fa (p>>1)
  31. struct node{
  32. int x,v;
  33. bool operator <(const node &a)const{return v<a.v;}
  34. }Q[N+10];
  35. int tot;
  36. void insert(int x,int v){
  37. Q[++tot]=(node){x,v};
  38. int p=tot;
  39. while (p!=1&&Q[p]<Q[fa]) swap(Q[p],Q[fa]),p=fa;
  40. }
  41. void Delete(){
  42. Q[1]=Q[tot--];
  43. int p=1,son;
  44. while (ls<=tot){
  45. if (rs>tot||Q[ls]<Q[rs]) son=ls;
  46. else son=rs;
  47. if (Q[son]<Q[p]) swap(Q[p],Q[son]),p=son;
  48. else break;
  49. }
  50. }
  51. }Heap;
  52. struct Segment{
  53. int tree[(N<<2)+10];
  54. Segment(){memset(tree,127,sizeof(tree));}
  55. void Add_tag(int p,int v){tree[p]=min(tree[p],v);}
  56. void pushdown(int p){
  57. if (tree[p]==inf) return;
  58. Add_tag(ls,tree[p]);
  59. Add_tag(rs,tree[p]);
  60. }
  61. void Modify(int p,int l,int r,int x,int y,int v){
  62. if (x<=l&&r<=y){
  63. Add_tag(p,v);
  64. return;
  65. }
  66. int mid=(l+r)>>1;
  67. if (x<=mid) Modify(ls,l,mid,x,y,v);
  68. if (y>mid) Modify(rs,mid+1,r,x,y,v);
  69. }
  70. void traversals(int p,int l,int r){
  71. if (l==r){
  72. if (tree[p]>Max) Max=tree[p],Ans=0;
  73. Ans+=tree[p]==Max;
  74. return;
  75. }
  76. pushdown(p);
  77. int mid=(l+r)>>1;
  78. traversals(ls,l,mid);
  79. traversals(rs,mid+1,r);
  80. }
  81. }Tree;
  82. struct S2{
  83. int dis[N+10];
  84. S2(){memset(dis,63,sizeof(dis));}
  85. }Frw,Bck;
  86. void join(int x,int y,int z){pre[++tot]=now[x],now[x]=tot,child[tot]=y,val[tot]=z;}
  87. void insert(int x,int y,int z){join(x,y,z),join(y,x,z);}
  88. void dijkstra(int x,int *dis){
  89. memset(vis,0,sizeof(vis));
  90. Heap.insert(x,dis[x]=0);
  91. while (Heap.tot){
  92. int Now=Heap.Q[1].x;
  93. Heap.Delete();
  94. if (vis[Now]) continue;
  95. vis[Now]=1;
  96. for (int p=now[Now],son=child[p];p;p=pre[p],son=child[p]){
  97. if (dis[son]>dis[Now]+val[p]){
  98. dis[son]=dis[Now]+val[p];
  99. Heap.insert(son,dis[son]);
  100. }
  101. }
  102. }
  103. }
  104. void Find_way(int x){
  105. In_way[x]=1;
  106. dfn[x]=num++;
  107. for (int p=now[x],son=child[p];p;p=pre[p],son=child[p]){
  108. if (Frw.dis[x]+val[p]+Bck.dis[son]==Dis){
  109. flag[p]=flag[p+(p&1?1:-1)]=1;
  110. Find_way(son);
  111. return;
  112. }
  113. }
  114. }
  115. void bfs(S2 T,int *A){
  116. int head=1,tail=0;
  117. for (int i=1;i<=n;i++) if (In_way[i]) A[h[++tail]=i]=dfn[i];
  118. for (;head<=tail;head++){
  119. int Now=h[head];
  120. for (int p=now[Now],son=child[p];p;p=pre[p],son=child[p]){
  121. if (!In_way[son]&&!A[son]&&T.dis[Now]+val[p]==T.dis[son]){
  122. h[++tail]=son;
  123. A[son]=A[Now];
  124. }
  125. }
  126. }
  127. }
  128. int main(){
  129. n=read(),m=read();
  130. for (int i=1;i<=m;i++){
  131. int x=read(),y=read(),z=read();
  132. insert(x,y,z);
  133. }
  134. dijkstra(1,Frw.dis);
  135. dijkstra(n,Bck.dis);
  136. Dis=Frw.dis[n];
  137. Find_way(1),num--;
  138. bfs(Frw,L),bfs(Bck,R);
  139. for (int x=1;x<=n;x++)
  140. for (int p=now[x],son=child[p];p;p=pre[p],son=child[p])
  141. if (!flag[p]&&~L[x]&&~R[son]&&L[x]<R[son])
  142. Tree.Modify(1,1,num,L[x]+1,R[son],Frw.dis[x]+val[p]+Bck.dis[son]);
  143. Tree.traversals(1,1,num);
  144. printf("%d %d\n",Max,Max==Dis?m:Ans);
  145. return 0;
  146. }

[TJOI2012]桥的更多相关文章

  1. P2685 [TJOI2012]桥

    P2685 [TJOI2012]桥 思路: 先求出最短路: d1[u] : u 到 1 的最短路, d2[u] : u 到 n 的最短路 再求出一条从 1 到 n 的最短路链,然后从链上的每一个点出发 ...

  2. 洛谷2685 [TJOI2012]桥

    [TJOI2012]桥 题目大意:给定一无向图,求删除一条边后1到n最短路的最大值,以及方案数. 做法:我们先从1为起点.从n为起点跑两边dij,获得每一个点到起点1.终点n的最短距离,其实距离和边权 ...

  3. [TJOI2012]桥(最短路+线段树)

    有n个岛屿, m座桥,每座桥连通两座岛屿,桥上会有一些敌人,玩家只有消灭了桥上的敌人才能通过,与此同时桥上的敌人会对玩家造成一定伤害.而且会有一个大Boss镇守一座桥,以玩家目前的能力,是不可能通过的 ...

  4. bzoj4400: tjoi2012 桥

    先传代码再填坑 #include <iostream> #include <cstdio> #include <cmath> #include <cstrin ...

  5. BZOJ4400 TJOI2012桥(最短路+线段树)

    首先找出任意一条1-n的最短路径.显然删除的边只有在该最短路上才会对最短路长度产生影响. 不会证明地给出一个找不到反例的结论:删除一条边后,新图中一定有一条1-n的最短路径上存在一条边x->y, ...

  6. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  7. BZOJ 3504: [Cqoi2014]危桥 [最大流]

    3504: [Cqoi2014]危桥 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1407  Solved: 703[Submit][Status] ...

  8. hub,桥,交换机,路由器的区别

    1.四种设备在网络中的物理位置 如下图 2.这四种设备的本质 这四种设备,不管怎样,他们都是进行包的转发,只不过转发的行为有些不一样而已 3.逐一介绍 对于hub,一个包过来后,直接将包转发到其他口. ...

  9. 游戏测评-桥梁建造系Poly Bridge破力桥?游戏测评

    最近在b站看到了谜之声的视频:大家来造桥吧! 实在是太搞笑了,看到是一款新出不久还未正式发行的游戏,兴致一来便入手玩了玩.顺手也就写下了这篇测评. POLY BRIDGE 对这个游戏名怎么起个有趣的中 ...

随机推荐

  1. Window Pains(poj 2585)

    题意: 一个屏幕要同时打开9个窗口,每个窗口是2*2的矩阵,整个屏幕大小是9*9,每个窗口位置固定. 但是是否被激活(即完整显示出来)不确定. 给定屏幕状态,问是否可以实现显示. 分析:拓扑排序,把完 ...

  2. [NOIP2007] 提高组 洛谷P1099 树网的核

    题目描述 设T=(V, E, W) 是一个无圈且连通的无向图(也称为无根树),每条边到有正整数的权,我们称T为树网(treebetwork),其中V,E分别表示结点与边的集合,W表示各边长度的集合,并 ...

  3. PatentTips - Hierarchical RAID system including multiple RAIDs

    BACKGROUND OF THE INVENTION The present invention relates to a storage system offering large capacit ...

  4. linux 常见名词及命令(六)

    查看软件安装位置 : dpkg -L 软件包名字 ubuntu环境的apache相关命令: 查看是否启动:ps -aux | grep httpd  或者 netstat -an | grep :80 ...

  5. nyoj_205_求余数_201404271630

    求余数 时间限制:1000 ms  |  内存限制:65535 KB 难度:3   描述 现在给你一个自然数n,它的位数小于等于一百万,现在你要做的就是求出这个数除10003之后的余数   输入 第一 ...

  6. P1547 Out of Hay 洛谷

    https://www.luogu.org/problem/show?pid=1547 题目背景 奶牛爱干草 题目描述 Bessie 计划调查N (2 <= N <= 2,000)个农场的 ...

  7. HTTPS 是如何保证安全的?

    每当我们讨论到信息安全的时候,我们最长接触到的信息加密传输的方式莫过于 HTTPS 了,当我们浏览器地址栏闪现出绿色时,就代表着这个网站支持 HTTPS 的加密信息传输方式,并且你与它的连接确实被加密 ...

  8. 图片在 canvas 中的 选中/平移/缩放/旋转,包含了所有canvas的2D变化,让你认识到数学的重要性

    1.介绍 canvas 已经出来好久了,相信大家多少都有接触. 如果你是前端页面开发/移动开发,那么你肯定会有做过图片上传处理,图片优化,以及图片合成,这些都是可以用 canvas 实现的. 如果你是 ...

  9. TensorFlow-GPU环境配置之四——配置和编译TensorFlow

    首先,使用configure进行配置 配置完成后,使用bazel编译retrain命令,编译命令中加入--config=cuda即为启用GPU 编译进行中... 编译完成 编译完成后,调用retrai ...

  10. FTP指令说明

    安装vsftpd: listen=YES: 是否监听端口 anonymous_enable=NO: 是否启用匿名用户 local_enable=YES: 是否允许本地用户登录 write_enable ...