日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

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

發布時間:2023/12/3 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 P2685 [TJOI2012]桥(最短路+线段树) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

P2685 [TJOI2012]橋

xcxcli題解
下面思路仿照上述題解,代碼基本照抄上述題解


u?vu\leadsto vu?v表示uuuvvv的最短路
u→vu\to vuv表示uuuvvv直接相連的邊
d1ud1_ud1u?表示1?u1\leadsto u1?u的最短路
dnudn_udnu?表示n?vn\leadsto vn?v的最短路

題意化簡一下就是讓你求刪除一條邊使得1?n1\leadsto n1?n最大化,并求刪邊方案數。

首先不難發現,如果我們選擇刪除的邊不在1?n1\leadsto n1?n的路徑上,并不會對1?n1\leadsto n1?n的大小產生影響,也就是如果要產生影響必須刪除該路徑上的一條邊。

不妨假設1?n1\leadsto n1?n路徑上的點如下
1→?→a→b→c→d→?→n1\to \dots\to a\to b{\color{red}\to} c \to d \to \dots \to n1?abcd?n
如果我們現在選擇刪除b→cb\to cbc這條邊,發現這條路徑被切成兩部分1→?→a→b1\to \dots\to a\to b1?abc→d→?→nc \to d \to \dots \to ncd?n,由于我們現在已經刪除b→cb\to cbc這條邊,新的1?n1\leadsto n1?n一定是1?x?u→v?y?n1\leadsto x\leadsto u\to v\leadsto y\leadsto n1?x?uv?y?n,并且x∈1→?→a→b,y∈c→d→?→nx\in 1\to \dots\to a\to b,y\in c \to d \to \dots \to nx1?ab,ycd?n

也就是我們現在讓其強制走一條不在1?n1\leadsto n1?n上的路徑即u→vu\to vuv,并且走此路徑能夠避開b→cb\to cbc1?x?u→v?y?n1\leadsto x\leadsto u\to v\leadsto y\leadsto n1?x?uv?y?n路徑的權值顯然是d1u+wu→v+dnvd1_u+w_{u\to v}+dn_vd1u?+wuv?+dnv?,讓其更新刪除b→cb\to cbc1?n1\leadsto n1?n的最短路。

顯然我們不能枚舉x,yx,yx,y然后在枚舉u→vu \to vuv去更新刪除b→cb\to cbc的結果,有一個直接的想法就是1?x?u→v?y?n1\leadsto x\leadsto u\to v\leadsto y\leadsto n1?x?uv?y?n路徑能夠避開哪些1→?→a→b→c→d→?→n1\to \dots\to a\to b{\color{red}\to} c \to d \to \dots \to n1?abcd?n的邊,假設它能夠避開a→b→c→da\to b\to c\to dabcd顯然這個結果能夠更新刪除a→ba\to bab或者b→cb\to cbc或者c→dc\to dcd的答案。

于是我們只需要枚舉u→vu\to vuv這條邊(需要保證此邊不在1?n1\leadsto n1?n的路徑上),然后找到1?x?u→v?y?n1\leadsto x\leadsto u\to v\leadsto y\leadsto n1?x?uv?y?n能夠避開哪些邊(仔細想想可知避開的路徑一定是連續的),進行區間更新(線段樹)即可。
這也是上述博客預處理LuL_uLu?RuR_uRu?的原因!!!

有了上述兩個數組那么1?x?u→v?y?n1\leadsto x\leadsto u\to v\leadsto y\leadsto n1?x?uv?y?n避開的路徑則是Lu?RvL_u \leadsto R_vLu??Rv?之間的邊。

dengyaotriangle詳細證明

#include<queue> #include<cstring> #include<iostream> #include<algorithm> using namespace std; using pii=pair<int,int>; constexpr int N=100010,M=400010; constexpr int INF=0x3f3f3f3f; int h[N],e[M],ne[M],w[M],idx; void add(int a,int b,int c){e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++;} int n,m; bool st[N]; int d1[N],dn[N]; int path[N],cnt,id[N]; bool in[M]; int L[N],R[N],ans[N]; void dijkstra(int S,int d[]) {memset(d,0x3f,(n+1)*sizeof(int));memset(st,0,sizeof st);d[S]=0;priority_queue<pii,vector<pii>,greater<pii> >q;q.push({0,S});while(q.size()){int u=q.top().second;q.pop();if(st[u]) continue;st[u]=1;for(int i=h[u];i!=-1;i=ne[i]){int v=e[i];if(d[v]<=d[u]+w[i]) continue;d[v]=d[u]+w[i];q.push({d[v],v});}} } void bfs(int k,int d[],int f[]) {queue<int> q;q.push(path[k]);f[path[k]]=k;while(q.size()){int u=q.front();q.pop();for(int i=h[u];i!=-1;i=ne[i]){int v=e[i];if(!id[v]&&!f[v]&&d[u]+w[i]==d[v]) f[v]=k,q.push(v);}} } struct node {int l,r,v; }tree[N<<2]; void build(int u,int l,int r) {tree[u]={l,r,INF};if(l==r) return;int mid=l+r>>1;build(u<<1,l,mid),build(u<<1|1,mid+1,r); } void modify(int u,int l,int r,int x) {if(tree[u].l>=l&&tree[u].r<=r) return tree[u].v=min(tree[u].v,x),void();int mid=tree[u].l+tree[u].r>>1;if(l<=mid) modify(u<<1,l,r,x);if(r>mid) modify(u<<1|1,l,r,x); } void pushdown(int u) {if(tree[u].l==tree[u].r){ans[tree[u].l]=tree[u].v;return;}tree[u<<1].v=min(tree[u<<1].v,tree[u].v);tree[u<<1|1].v=min(tree[u<<1|1].v,tree[u].v);int mid=tree[u].l+tree[u].r>>1;pushdown(u<<1),pushdown(u<<1|1);} int main() {cin>>n>>m;memset(h,-1,sizeof h);for(int i=1;i<=m;i++){int a,b,c;cin>>a>>b>>c;add(a,b,c),add(b,a,c);}dijkstra(1,d1),dijkstra(n,dn);// 預處理1->n路徑上的點int u=1;while(u!=n){path[++cnt]=u;id[u]=cnt;for(int i=h[u];i!=-1;i=ne[i]){int v=e[i];if(dn[v]+w[i]==dn[u]) {in[i]=1;u=v;break;}}}path[++cnt]=n;id[n]=cnt;//1->n路徑上的點 for(int i=1;i<=cnt;i++) bfs(i,d1,L),bfs(i,dn,R);--cnt;build(1,1,cnt);//我們將1->n路徑上的邊編號for(int u=1;u<=n;u++)for(int i=h[u];i!=-1;i=ne[i]){int v=e[i];if(!in[i]&&L[u]<R[v])// L[u]->R[v]邊的編號是L[u]->R[v]-1modify(1,L[u],R[v]-1,d1[u]+w[i]+dn[v]);}pushdown(1);int mx=0,res=0;for(int i=1;i<=cnt;i++){if(mx<ans[i]) mx=ans[i],res=1;else if(mx==ans[i]) res++;}if(mx==d1[n]) res=m;cout<<mx<<' '<<res<<'\n'; }

總結

以上是生活随笔為你收集整理的P2685 [TJOI2012]桥(最短路+线段树)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。