1. 程式人生 > >codeforces464E The Classic Problem -- 最短路+主席樹+Hash

codeforces464E The Classic Problem -- 最短路+主席樹+Hash

題目大意:

st的最短路,邊權為2xi,xi105

程式碼:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<queue>
#include<map>
using namespace std;
#define N 100010
#define P 1000000007
#define INF 1e6
typedef unsigned
long long ull; struct Edge{ int t,nx,w; }e[N<<1]; struct Node{ ull w; int l,r,f; }c[N*280]; struct Interval{ int l,r; Interval(int l=0,int r=0):l(l),r(r){} bool operator < (Interval a)const{ return l<a.l||(l==a.l&&r<a.r); } }; map<Interval,int
>
Map; ull p[N+100]; int i,j,k,n,m,h[N],x,y,z,d[N],Num,t,M,Pre[N],Cnt,g[N],B; bool b[N]; inline bool Cmp(int x,int y,int l,int r){ if(l==r)return c[x].w>c[y].w; int Mid=l+r>>1; if(c[c[x].r].w==c[c[y].r].w)return Cmp(c[x].l,c[y].l,l,Mid); return Cmp(c[x].r,c[y].r,Mid+1,r); } struct
A{ int Rt,f; A(int Rt=0,int f=0):Rt(Rt),f(f){} bool operator < (A a)const{ return Cmp(Rt,a.Rt,1,M); } }Tmp; priority_queue<A>Q; inline int Max(int x,int y){ return x<y?y:x; } inline int Min(int x,int y){ return x<y?x:y; } inline void Add(int x,int y,int z){ e[++t].t=y;e[t].nx=h[x];h[x]=t;e[t].w=z; } inline void Up(int x){ c[x].w=c[c[x].l].w*7+c[c[x].r].w*11; c[x].f=c[c[x].l].f<INF?c[c[x].l].f:c[c[x].r].f; } inline void Build(int& x,int l,int r){ x=++Num;Map[Interval(l,r)]=x; if(l==r){ c[x].f=l; return; } int Mid=l+r>>1; Build(c[x].l,l,Mid); Build(c[x].r,Mid+1,r); Up(x); } inline int Update2(int x,int l,int r,int y){ int z=++Num;c[z]=c[x]; if(l==r){ c[z].w=p[l]; c[z].f=INF; return z; } int Mid=l+r>>1; if(y<=Mid)c[z].l=Update2(c[x].l,l,Mid,y);else c[z].r=Update2(c[x].r,Mid+1,r,y); Up(z); return z; } inline int Update3(int x,int l,int r,int L,int R){ if(l>=L&&r<=R)return Map[Interval(l,r)]; int Mid=l+r>>1,y=++Num;c[y]=c[x]; if(Mid>=L)c[y].l=Update3(c[x].l,l,Mid,L,R); if(Mid<R)c[y].r=Update3(c[x].r,Mid+1,r,L,R); Up(y); return y; } inline int Find(int x,int l,int r,int y){ if(l==r)return c[x].f; int Mid=l+r>>1; if(y<=Mid)return Min(Find(c[x].l,l,Mid,y),c[c[x].r].f); return Find(c[x].r,Mid+1,r,y); } inline int Update1(int x,int y){ int z=Find(x,1,M,y); int a1=Update2(x,1,M,z); if(z>y)a1=Update3(a1,1,M,y,z-1); return a1; } inline int Getval(int x,int l,int r){ if(l==r){ int ret=c[x].w?B:0; return B=(B<<1)%P,ret; } int Mid=l+r>>1; return (Getval(c[x].l,l,Mid)+Getval(c[x].r,Mid+1,r))%P; } int main(){ scanf("%d%d",&n,&m); for(i=1;i<=m;i++)scanf("%d%d%d",&x,&y,&z),Add(x,y,++z),Add(y,x,z),M=Max(M,z); for(i=1;1<<i<n;i++);M+=i; for(i=p[0]=1;i<=M;i++)p[i]=p[i-1]*5; scanf("%d%d",&x,&y); if(x==y){ printf("0\n1\n%d\n",x); return 0; } Build(d[x],1,M); Q.push(A(d[x],x)); while(!Q.empty()){ Tmp=Q.top();Q.pop(); if(d[Tmp.f]!=Tmp.Rt)continue; for(int i=h[Tmp.f];i;i=e[i].nx){ z=Update1(d[Tmp.f],e[i].w); if(!b[e[i].t]||Cmp(d[e[i].t],z,1,M)){ b[e[i].t]=1;d[e[i].t]=z;Pre[e[i].t]=Tmp.f; Q.push(A(z,e[i].t)); } } } if(!b[y])printf("-1\n");else{ B=1; printf("%d\n",Getval(d[y],1,M)); for(i=y;i!=x;i=Pre[i])g[++Cnt]=i; printf("%d\n%d ",Cnt+1,x); for(i=Cnt;i;i--)printf("%d ",g[i]); } return 0; }

相關推薦

codeforces464E The Classic Problem -- 短路+主席+Hash

題目大意: 求s到t的最短路,邊權為2xi,xi≤105。 程式碼: #include<iostream> #include<cstdio> #include<cstring> #include<alg

Codeforces 464E The Classic Problem (短路 + 主席 + hash

The jks main hup def cmp rhs sign code 題意及思路 這個題加深了我對主席樹的理解,是個好題。每次更新某個點的距離時,是以之前對這個點的插入操作形成的線段樹為基礎,在O(logn)的時間中造出了一顆新的線段樹,相比直接創建n顆線段樹更省

[短路 主席 Hash] Codeforces 464E #265 (Div. 1) E. The Classic Problem

很棒的資料結構練習題 因為邊權太大了 我們不能直接儲存 我們用主席樹! 比較直接從高位到低位找第一個不同的位 可以Hash下 每次加法 我們找到這一位之後第一個0 那麼0變為1 0之前一連串1都變成0 這裡有個小trick可以不用打標記 我們先建一棵全

[短路 && 主席維護HASH] 51nod1863 Travel

傳送門 把一條路徑上的點值按排名順序排序,那麼路徑的優劣就是字典序。 相當於是求一條字典序最大的路徑。 最長路 然後就是老套路,用主席樹來維護hash,就可以在O(log)的時間裡比較兩個串的字典序,然後就套最短路就可以了 用對優化的DIJ複雜度就是O(

CodeForces 464E The Classic Problem | 呆克斯歘 主席維護高精度

ring 問題: || con .html 每次 tin -- ace 題意描述 有一個\(n\)點\(m\)邊的無向圖,第\(i\)條邊的邊權是\(2^{a_i}\)。求點\(s\)到點\(t\)的最短路長度(對\(10^9 + 7\)取模)。 題解 思路很簡單——用

HDU1142 A Walk Through the Forest(短路+DAG)

input ica highlight iss diff wan before star length A Walk Through the Forest Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 6

短路 BZOJ3694 鏈剖分+線段

OS 情況 ostream 最小值 down from == spa sizeof 分析: 樹剖裸題,[Usaco2009 Jan]安全路經Travel 的簡化版 剖開最短路樹,遍歷每一條沒在最短路樹上的邊。 這種情況下,有且僅有u到v路徑上,出來lca之外的點能夠通

HDU 1142 A Walk Through the Forest(短路+記憶化搜索)

大於 take tin href init sizeof itl any problem A Walk Through the Forest Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/327

CF 464E The Classic Problem

進行 dijk hid htm operator logs one http 在線 補一補之前聽課時候的題。 考慮使用dij算法求最短路,因為邊權存不下,所以考慮用主席樹維護二進制位,因為每一次都只會在一個位置進行修改,所以可以暴力進位,這樣均攤復雜度是對的。 《算法導

gym 101064 G.The Declaration of Independence (主席

直接 兩個 enc upd () class 我們 lar 元素 題目鏈接: 題意: n個操作,有兩種操作: E p c 在序號為p的隊列尾部插入c得到新的隊列,序號為i D p 查詢並刪除序號為p的隊列頂部的元素,得到序號為i的新隊列 思路: 需要

[短路/線段大法優化DIJ] 【模板】單源短路徑(標準版)

洛谷原題 這題我自己看了STL優先佇列後試了試優化DIJ演算法,但我這個菜比只有32分... 還是老老實實用線段樹吧! 自己寫的程式,反正AC了,線段樹大法好! 具體見程式碼 #include<bits/stdc++.h> using namespace std; long lon

[bzoj2725]故鄉的夢——短路+線段 dalaos' blogs Some Links

題目大意: 給定一個帶權無向圖,每次詢問刪除一條邊之後從S到T的最短路是多少?(各個詢問之間獨立) 思路: 如果刪除的邊不在最短路中或者可以被替換,那麼答案即為最短路。 如果刪除的邊在最短路中並且不可以被替換,考慮將這條邊刪除的新圖: 假設原來的最短路為

The Doors(幾何+短路,好題)

The Doors http://poj.org/problem?id=1556 Time Limit: 1000MS   Memory Limit: 10000K Total Submis

CF 1051F The Shortest Statement (短路)

題目大意:一個無向連通圖,n個點m條邊,n<=1e5,m-n<=20,q個詢問,q<=1e5,求u和v之間的最短路 發現邊只比點多20個,所以可以把圖當成一棵樹,求出圖的最小生成樹 對於一個詢問,最短路徑可能是兩個點的樹上最小距離,但最短路徑也有可能經過未被加入最小生成樹的邊 那怎麼辦

洛谷3783 SDOI2017 天才黑客(短路+虛+邊轉點+線段優化建圖)

題目連結 成功又一次自閉了 怕不是豬國殺之後最自閉的一次 一看到最短路徑。 我們就能推測這應該是個最短路題 現在考慮怎麼建圖 根據題目的意思,我們可以發現,在本題中,邊與邊之間存在一些轉換關係,但是點與點之間並不存在。 那麼我們考慮 邊轉點,點轉邊。 每一條邊拆成

Codeforces 786B Legacy 短路+線段

不錯的題目,這次不偷qsc得了,偷個別人的 傳送門  題目意思很簡單,就是你有三種操作:  1 u v w 從u向v連一條權值為w的有向邊  2 u L R w 從u向L至R的所有結點連一條權值為w的有向邊  3 u L R w 從L至R的所有結點向u連一條權值為w的

[bzoj2725]故鄉的夢——短路+線段

題目大意: 給定一個帶權無向圖,每次詢問刪除一條邊之後從S到T的最短路是多少?(各個詢問之間獨立) 思路: 如果刪除的邊不在最短路中或者可以被替換,那麼答案即為最短路。 如果刪除的邊在最短路中並且不可以被替換,考慮將這條邊刪除的新圖: 假設原來的最短路為S−&a

Codechef Aug2017 #Walks on the binary tree -- 主席+Hash

傳送門 每次答案增加的值就是 n - 之前出現的數與 X 的 LCP 最大值。 而與 X 的 LCP 最大的點在 dfs 序上與 X 的距離最近。而在滿二叉樹上 X 在 dfs 序上的位置就等於 X 。 於是可以用 set 維護所有出現過的點,加入 X 時

Educational Codeforces Round 51 (Rated for Div. 2) F. The Shortest Statement (短路+LCA)

原題地址:http://codeforces.com/contest/1051/problem/F 題意:給你nnn個點,mmm條邊。m−n&lt;=20m-n&lt;=20m−n<=20。保證圖連通 問你任意兩點的最短距離是多少。 思路:

bzoj4435: [Cerc2015]Juice Junctions(小割+hash

ostream printf tdi amp mes moto blog pen .com 傳送門 首先最大流等於最小割,那麽可以轉化為最小割樹來做(不知道什麽是最小割樹的可以看看這題->這裏) 具體的做法似乎是$hash[i][j]$表示最小割為$i$時點