P1821 [USACO07FEB]银牛派对Silver Cow Party
三倍经验
这三道题思想比较像的,只不过第一道的数据大了很多,于是就成蓝题了.
因为如果数据小了的话,如第二题和第三题,可以跑n遍最短路.
于是我就来讲讲第一题的做法.
从起点出发,到每一个节点,明显可知这是一个单源多终点的最短路模型.
但是回来的时候,是从多个点回到终点,是一个多源单终点的最短路.
跑floyd任意点间的最短路肯定不行,O(n^3)的时间复杂度.
再来想一想,回来的时候多个点通向同一个点,要是反过来的话,就是单源多终点的最短路了.
扫描二维码关注公众号,回复:
6557780 查看本文章
于是可以反向存边,从起点跑到每一个点,dis数组里就有了从这个点到起点回来时的最短路.
总体来说就是反向存边跑一遍Dijkstra,正向存边跑一遍Dijkstra.
代码如下,挺简单的就不注释了(请忽略如"zzq太可爱了"之类的言论).
PS:按照我的习惯,我打每一行都要打个缩进,但是我把vim设置了保持当前缩进,于是复制下来就这样了......凑合着看吧.
#include<bits/stdc++.h>
#define ll long long
using namespace std;
priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > >q1,q2;
struct edge
{
ll next,to,val;
}e1[1000010],e2[1000010];
ll n,m,size1,size2,ans;
ll head1[1000010],head2[1000010];
ll dis1[1000010],dis2[1000010];
bool falg1[1000010],falg2[1000010];
void add_edge1(ll,ll,ll);
void add_edge2(ll,ll,ll);
void Dij1();
void Dij2();
int main()
{
memset(head1,-1,sizeof(head1));
memset(head2,-1,sizeof(head2));
scanf("%lld%lld",&n,&m);
for(ll i=1;i<=m;i++)
{
ll a,b,val;
scanf("%lld%lld%lld",&a,&b,&val);
add_edge1(a,b,val);
add_edge2(b,a,val);
}
Dij1();
Dij2();
// for(int i=1;i<=n;i++)printf("%d ",dis1[i]);
// printf("\n");
// for(int i=1;i<=n;i++)printf("%d ",dis2[i]);
for(ll i=2;i<=n;i++)ans+=dis1[i]+dis2[i];
printf("%lld\n",ans);
return 0;
}
void add_edge1(ll from,ll to,ll val)
{
e1[++size1].to=to;
e1[size1].val=val;
e1[size1].next=head1[from];
head1[from]=size1;
// printf("zzqtql%d\n",size1);
}
void add_edge2(ll from,ll to,ll val)
{
e2[++size2].to=to;
e2[size2].val=val;
e2[size2].next=head2[from];
head2[from]=size2;
}
void Dij1()
{
memset(dis1,0x3f,sizeof(dis1));
// printf("zzqtkal%d",dis1[3]);
memset(falg1,0,sizeof(falg1));
dis1[1]=0;
q1.push(make_pair(dis1[1],1));
while(!q1.empty())
{
ll x=q1.top().second;
q1.pop();
if(falg1[x]==true)continue;
falg1[x]=true;
for(ll i=head1[x];i!=-1;i=e1[i].next)
{
ll val=e1[i].val;
ll to=e1[i].to;
if(dis1[to]>dis1[x]+val)
{
dis1[to]=dis1[x]+val;
q1.push(make_pair(dis1[to],to));
}
// printf("zzqakioi%d%d\n",val,dis1[to]);
}
}
}
void Dij2()
{
memset(dis2,0x3f,sizeof(dis2));
memset(falg2,0,sizeof(falg2));
dis2[1]=0;
q2.push(make_pair(dis2[1],1));
while(!q2.empty())
{
ll x=q2.top().second;
q2.pop();
if(falg2[x]==true)continue;
falg2[x]=true;
for(ll i=head2[x];i!=-1;i=e2[i].next)
{
ll val=e2[i].val;
ll to=e2[i].to;
if(dis2[to]>dis2[x]+val)
{
dis2[to]=dis2[x]+val;
q2.push(make_pair(dis2[to],to));
}
}
}
}