1 题目大意
给你一个源点,让你从这里派发学生到其余的点邀请人们去CSS,然后这些学生再返回源点,求使得学生总的cost最小的值。
2 解题思路
(1)从源点出去的时候:求一次最短路,将所有的d[i]相加。
(2)从其他点回来的时候:将有向边反向,由于题目保证所有的点均可到达,所以SPFA源点,然后相加可得结果。
3 代码
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
#define MAXV 1000000
#define MAXE 1000000
#define MAXINT 999999999
typedef struct
{
int from;
int to;
int weight;
int next1;
int next2;
}Edge;
int nv, ne, tot;
int dis[MAXV], vis[MAXV], index1[MAXV], index2[MAXV];
Edge edge[MAXE];
void init()
{
tot=0;
memset(index1, -1, sizeof(index1));
memset(index2, -1, sizeof(index2));
}
void insert_edge(int s, int t, int w)
{
edge[tot].from=s;
edge[tot].to=t;
edge[tot].weight=w;
edge[tot].next1=index1[s];
edge[tot].next2=index2[t];
index1[s]=index2[t]=tot;
tot++;
}
long long spfa(int s, int t)
{
int i, u, v, w;
long long sum;
queue<int> que;
sum=0;
//第一次spfa,求源点到所有点的最短距离
for(i=0;i<=nv;i++)
{
dis[i]=MAXINT;
vis[i]=0;
}
dis[s]=0;
que.push(s);
vis[s]=1;
while(!que.empty())
{
u=que.front();
que.pop();
vis[u]=0;
for(i=index1[u];i!=-1;i=edge[i].next1)
{
v=edge[i].to;
w=edge[i].weight;
if(dis[v]>dis[u]+w)
{
dis[v]=dis[u]+w;
if(!vis[v])
{
que.push(v);
vis[v]=1;
}
}
}
}
//求源点到其他点的距离之和
for(i=1;i<=nv;i++)
{
if(dis[i]<MAXINT)
sum+=dis[i];
}
//第二次spfa,求所有点到源点的最短距离
for(i=0;i<=nv;i++)
{
dis[i]=MAXINT;
vis[i]=0;
}
dis[s]=0;
que.push(s);
vis[s]=1;
while(!que.empty())
{
u=que.front();
que.pop();
vis[u]=0;
for(i=index2[u];i!=-1;i=edge[i].next2)
{
v=edge[i].from;
w=edge[i].weight;
if(dis[v]>dis[u]+w)
{
dis[v]=dis[u]+w;
if(!vis[v])
{
que.push(v);
vis[v]=1;
}
}
}
}
//求其他点到源点的距离之和
for(i=1;i<=nv;i++)
{
if(dis[i]<MAXINT)
sum+=dis[i];
}
return sum;
}
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
scanf("%d%d", &nv, &ne);
int a, b, c, i;
init();
for(i=0;i<ne;i++)
{
scanf("%d%d%d", &a, &b, &c);
insert_edge(a, b, c);
}
printf("%lld\n", spfa(1, nv));
}
return 0;
}