您的位置:首页 > 其它

多校round2-day2-t2 净化

2016-10-09 20:08 148 查看
dij预处理水厂到各个点的最短路,对于每条边,我们做一下处理

单向边

ans=max(ans,f[i]+len[j])

双向边有可能是两边合起来,所以

Ans−f[x]+Ans−f[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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: