bzoj 4400 tjoi2012 桥
Description
有n个岛屿,m座桥,每座桥连通两座岛屿,桥上会有一些敌人,玩家只有消灭了桥上的敌人才能通过,与此同时桥上的敌人会对玩家造成一定伤害。而且会有一个大Boss镇守一座桥,以玩家目前的能力,是不可能通过的。而Boss是邪恶的,Boss会镇守某一座使得玩家受到最多的伤害才能从岛屿1到达岛屿n(当然玩家会选择伤害最小的路径)。问,Boss可能镇守桥有哪些。
Input
第一行两个整数n,m 接下来m行,每行三个整数s,t,c,表示一座连接岛屿s和t的桥上的敌人会对玩家造成c的伤害。
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 HINT
100%的数据,1<=n<=100000,1<=m<=200000,1<=c<=10000,数据保证玩家可以从岛屿1到达岛屿n
Source
首先我们删除的边一定是在1~n的最短路路径上的一条边 那么假设是x->y并且x是y的父节点 那么我们需要满足 新边A->B 那么可以知道S->A->B->T 只要保证这三部分都不经过x->y即可
那么我们可以知道 A一定不在y的子树内 B一定在y的子树内 因为A所有地方都能走就是不能走到子树里 否则走的就不是最短路了 然后只要B在y的子树内就一定不会经过x->y这条边 因为因为B走到y再走到x再走到y会发现他重复走了 一段路 不如直接走y即可 所以B在y的子树内就可以了
然后找出1~n这条路的这条链 然后给这条链进行标号将深度从浅到深进行标号
然后给其他的点也都标号 标 该点与n节点lca的编号即可 然后考虑枚举每条非树边
每条非树边对应的编号就分别是这条链上的编号 也就是如果我必须经过这条边 那么中间这条链上dep[x]~dep[y]这些边都可以被砍掉 那么我就算一个我必须走这条边的代价 然后去线段树上区间取最小值即可
最后遍历整个线段树 找出最小值的最大即可
#include#include#include#include#include#include#define lc (x<<1)#define rc (x<<1|1)#define pa pairusing namespace std;inline char gc(){ static char now[1<<16],*S,*T; if (T==S){T=(S=now)+fread(now,1,1<<16,stdin);if (T==S) return EOF;} return *S++; }inline int read(){ int x=0,f=1;char ch=gc(); while(!isdigit(ch)) {if (ch=='-') f=-1;ch=gc();} while(isdigit(ch)) x=x*10+ch-'0',ch=gc(); return x*f; }const int N=1e5+10;const int inf=0x3f3f3f3f;struct node{ int x,y,z,next;}data[N<<2];int mn[N<<2],h[N],num=1,path[N],n,m,dis1[N],dis2[N],top,dep[N],fa[N],mx,ans;bool flag[N],in[N<<2];vectorson[N];inline void dijkstra1(){ priority_queue,greater >q; memset(dis1,0x3f,sizeof(dis1));dis1[1]=0;q.push(make_pair(0,1)); while(!q.empty()){ int x=q.top().second;q.pop();if (flag[x]) continue;flag[x]=1; for (int i=h[x];i;i=data[i].next){ int y=data[i].y,z=data[i].z; if(dis1[x]+z,greater >q; memset(dis2,0x3f,sizeof(dis2));memset(flag,0,sizeof(flag)); dis2[n]=0;q.push(make_pair(0,n)); while(!q.empty()){ int x=q.top().second;q.pop();if (flag[x]) continue;flag[x]=1; for (int i=h[x];i;i=data[i].next){ int y=data[i].y,z=data[i].z; if (dis2[x]+z>1; build(lc,l,mid);build(rc,mid+1,r);}inline void modify(int x,int l,int r,int l1,int r1,int v){ if(l1<=l&&r1>=r) {mn[x]=min(mn[x],v);return;}int mid=l+r>>1; if (l1<=mid) modify(lc,l,mid,l1,r1,v);if (r1>mid) modify(rc,mid+1,r,l1,r1,v);}inline void pushdown(int x){ mn[lc]=min(mn[lc],mn[x]);mn[rc]=min(mn[rc],mn[x]);}inline void query(int x,int l,int r){ if (l==r) {mx=max(mx,mn[x]);return;}int mid=l+r>>1; pushdown(x);query(lc,l,mid);query(rc,mid+1,r);}inline void query1(int x,int l,int r){ if (l==r) {if(mx==mn[x]) ++ans;return;}int mid=l+r>>1; query1(lc,l,mid);query1(rc,mid+1,r);}int q[N];int main(){ freopen("bzoj4400.in","r",stdin);// freopen("bzoj4400.out","w",stdout); n=read();m=read(); for (int i=1;i<=m;++i){ int x=read(),y=read(),z=read(); data[++num].y=y;data[num].next=h[x];data[num].x=x;h[x]=num;data[num].z=z; data[++num].y=x;data[num].next=h[y];data[num].x=y;h[y]=num;data[num].z=z; }dijkstra1();dijkstra2();q[top=1]=n; for (int i=n;fa[i];i=fa[i]) q[++top]=fa[i];build(1,1,top-1); for (int i=1,j=top;iyy) swap(x,y),swap(xx,yy);int dis=dis1[x]+dis2[y]+data[i].z; //printf("%d %d\n",xx,yy); modify(1,1,top-1,xx,yy-1,dis);//printf("%d\n",dis); }mx=0;query(1,1,top-1);query1(1,1,top-1); if(mx==dis1[n]) ans=m; printf("%d %d\n",mx,ans); return 0;}
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
暂时没有评论,来抢沙发吧~