题目来源
洛谷P1342 请柬
https://www.luogu.org/problem/show?pid=1342
洛谷P1629 邮递员送信
https://www.luogu.org/problem/show?pid=1629
洛谷P1821 [USACO07FEB]银牛派对Silver Cow Party
https://www.luogu.org/problem/show?pid=1821
思路
按照题目所给的边的信息建图
做一遍以1为源点的SPFA 求由总部1到各站点的最短路
对于[请柬]/[邮递员送信] ans+=∑dis1[i](i=1 to n)
反向建图 即把题目描述的边的起始点和目的地颠倒 重新建图
在新建的图上再做一遍以1为源点的SPFA求由总部1到各站点的最短路 即在原图上各站点到总部的最短路
对于[请柬]/[邮递员送信] ans+=∑dis2[i](i=1 to n)
对于[银牛派对] ans=max(dis1[i]+dis2[i])(i=1 to n)
代码(C++)[请柬/邮递员送信]
#include <cstdio>
#include <queue>
#include <bitset>
#define N 1000010//邮递员送信 1010
#define M 2000010//邮递员送信 200010
using namespace std;
bitset<N> in; queue<int> q;
int n,m,s,u,v,w,cnt=0,pos,k;
int he[N],he1[N];long long dis[N],ans=0;
struct way{int en,ne,len;}p[M];
inline void add();
inline void add1();
inline void rebuild();
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;++i)
scanf("%d%d%d",&u,&v,&w),add();
for(int i=1;i<=n;++i)
dis[i]=9223372036854775807;
s=1; dis[s]=0; in[s]=1; q.push(s);
while(!q.empty())
{
pos=q.front(); q.pop(); in[pos]=0;
k=he[pos];
while(k!=0)
{
if(dis[pos]+p[k].len<dis[p[k].en])
{
dis[p[k].en]=dis[pos]+p[k].len;
if(in[p[k].en]==0)
q.push(p[k].en);
in[p[k].en]=1;
}
k=p[k].ne;
}
}
for(int i=1;i<=n;++i)
ans+=dis[i],dis[i]=0;
rebuild();
for(int i=1;i<=n;++i)
dis[i]=9223372036854775807;
s=1; dis[s]=0; in[s]=1; q.push(s);
while(!q.empty())
{
pos=q.front(); q.pop(); in[pos]=0;
k=he1[pos];
while(k!=0)
{
if(dis[pos]+p[k].len<dis[p[k].en])
{
dis[p[k].en]=dis[pos]+p[k].len;
if(in[p[k].en]==0)
q.push(p[k].en);
in[p[k].en]=1;
}
k=p[k].ne;
}
}
for(int i=1;i<=n;++i)
ans+=dis[i];
printf("%lld",ans);
return 0;
}
inline void rebuild()
{
for(int i=1;i<=n;++i)
{
k=he[i]; v=i;
while(k!=0)
{
u=p[k].en;
w=p[k].len;
add1();
k=p[k].ne;
}
}
return ;
}
inline void add()
{
p[++cnt].en=v; p[cnt].len=w;
p[cnt].ne=he[u]; he[u]=cnt;
}
inline void add1()
{
p[++cnt].en=v; p[cnt].len=w;
p[cnt].ne=he1[u]; he1[u]=cnt;
}
代码(C++)[银牛派对]
#include <cstdio>
#include <queue>
#include <bitset>
#define N 1010
#define M 200010
using namespace std;
bitset<N> in; queue<int> q;
int n,m,s,u,v,w,cnt=0,pos,k;
int he[N],he1[N];long long dis[N],dis1[N],ans=0;
struct way{int en,ne,len;}p[M];
inline void add();
inline void add1();
inline void rebuild();
int main()
{
scanf("%d%d%d",&n,&m,&s);
for(int i=1;i<=m;++i)
scanf("%d%d%d",&u,&v,&w),add();
for(int i=1;i<=n;++i)
{
dis[i]=9223372036854775807;
dis1[i]=9223372036854775807;
}
dis[s]=0; in[s]=1; q.push(s);
while(!q.empty())
{
pos=q.front(); q.pop(); in[pos]=0;
k=he[pos];
while(k!=0)
{
if(dis[pos]+p[k].len<dis[p[k].en])
{
dis[p[k].en]=dis[pos]+p[k].len;
if(in[p[k].en]==0)
q.push(p[k].en);
in[p[k].en]=1;
}
k=p[k].ne;
}
}
rebuild();
dis1[s]=0; in[s]=1; q.push(s);
while(!q.empty())
{
pos=q.front(); q.pop(); in[pos]=0;
k=he1[pos];
while(k!=0)
{
if(dis1[pos]+p[k].len<dis1[p[k].en])
{
dis1[p[k].en]=dis1[pos]+p[k].len;
if(in[p[k].en]==0)
q.push(p[k].en);
in[p[k].en]=1;
}
k=p[k].ne;
}
}
for(int i=1;i<=n;++i)
if(dis[i]+dis1[i]>ans)
ans=dis[i]+dis1[i];
printf("%lld",ans);
return 0;
}
inline void rebuild()
{
for(int i=1;i<=n;++i)
{
k=he[i]; v=i;
while(k!=0)
{
u=p[k].en;
w=p[k].len;
add1();
k=p[k].ne;
}
}
return ;
}
inline void add()
{
p[++cnt].en=v; p[cnt].len=w;
p[cnt].ne=he[u]; he[u]=cnt;
}
inline void add1()
{
p[++cnt].en=v; p[cnt].len=w;
p[cnt].ne=he1[u]; he1[u]=cnt;
}