多校round2-day2-t2 淨化
阿新 • • 發佈:2019-02-11
dij預處理水廠到各個點的最短路,對於每條邊,我們做一下處理
單向邊
雙向邊有可能是兩邊合起來,所以
#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;
}