1. 程式人生 > >多校round2-day2-t2 淨化

多校round2-day2-t2 淨化

dij預處理水廠到各個點的最短路,對於每條邊,我們做一下處理
單向邊
ans=max(ans,f[i]+len[j])
雙向邊有可能是兩邊合起來,所以
Ansf[x]+Ansf[y]>=len[j]
d=len[j]+f[x]+f[y]
2Ans=d
ans=max(ans,d/2+d%2)

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#define ll long long
using namespace std;
int
n,m,x,y,z,t,ty,tot; int a[25005],heap[25005],pos[25005],head[25005]; ll f[25005]; int Next[600005],to[600005],len[600005],flag[600005]; void up(int id) { while(id/2>=1) { if(f[heap[id]]<f[heap[id/2]]) { swap(heap[id],heap[id/2]); swap(pos[heap[id]],pos[heap[id/2]]); id=id/2
; } else break; } } void down(int id) { while(id*2<=ty) { int j; if(id*2+1>ty||f[heap[id*2+1]]>f[heap[id*2]]) j=id*2;else j=id*2+1; if(f[heap[j]]<f[heap[id]]) { swap(heap[j],heap[id]); swap(pos[heap[j]],pos
[heap[id]]); id=j; } else break; } } ll dij() { for(int i=1;i<=n;i++) if(a[i]==1) { ty++; heap[ty]=i; pos[i]=ty; f[i]=0; } else { pos[i]=0; f[i]=1e10; } while(ty>0) { int x=heap[1]; swap(heap[1],heap[ty]); swap(pos[heap[1]],pos[heap[ty]]); ty--; down(1); for(int i=head[x];i!=-1;i=Next[i]) if(f[x]+len[i]<f[to[i]]) { f[to[i]]=f[x]+len[i]; if(pos[to[i]]==0) { ty++; heap[ty]=to[i]; pos[to[i]]=ty; } up(pos[to[i]]); } } ll ans=0; for(int i=1;i<=n;i++) for(int j=head[i];j!=-1;j=Next[j]) if(flag[j]==1) { ans=max(ans,f[i]+len[j]); } else { ll dis=f[i]+f[to[j]]+len[j]; ans=max(ans,dis/2+dis%2); } return ans; } void add(int x,int y,int z,int t) { Next[tot]=head[x]; to[tot]=y; len[tot]=z; flag[tot]=t; head[x]=tot; tot++; } int main() { cin>>n>>m; for(int i=1;i<=n;i++) { scanf("%d",&a[i]); head[i]=-1; } for(int i=1;i<=m;i++) { scanf("%d%d%d%d",&x,&y,&t,&z); if(t==1) { add(x,y,z,1); } else { add(x,y,z,2); add(y,x,z,2); } } cout<<dij(); return 0; }