/*题意:求1到其他点的最小值的和sum1,再求其他点到1的最小值的和sum2,最后sum=sum1+sum2,输出sum;
分析:两个spfa加一个反转图搞定*/
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
#include<iostream>
using namespace std;
#define LL long long
const int inf=1<<30;
const int maxm=1e6+10;
int vis[maxm],cnt[maxm],next[maxm],head[maxm],dist[maxm],pre[maxm];
int n,m,e;
int v[maxm],u[maxm],c[maxm];
queue<int>q;
void addage(int u,int v,int c)
{
next[e]=head[u];
head[u]=e++;
}
void turn()//反转图(***)
{
int i,k;
for(i=0;i<=m;i++)
{
head[i]=next[i]=-1;
}
for(i=0;i<m;i++)
{
k=v[i];
next[i]=head[k];
head[k]=i;
}
}
void spfa1(int st)
{
for(int i=0;i<=n;i++)
{
dist[i]=inf;
}
dist[st]=0;
q.push(st);
while(!q.empty())
{
int k=q.front();
q.pop();
vis[k]=0;
for(int i=head[k];i!=-1;i=next[i])
{
if(dist[v[i]]>dist[k]+c[i])
{
pre[v[i]]=k;
dist[v[i]]=dist[k]+c[i];
if(!vis[v[i]])
{
if(++cnt[v[i]]==n)
return;
q.push(v[i]);
vis[v[i]]=1;
}
}
}
}
return;
}
void spfa2(int st)
{
for(int i=0;i<=n;i++)
{
dist[i]=inf;
}
dist[st]=0;
q.push(st);
while(!q.empty())
{
int k=q.front();
q.pop();
vis[k]=0;
for(int i=head[k];i!=-1;i=next[i])
{
if(dist[u[i]]>dist[k]+c[i])
{
pre[u[i]]=k;
dist[u[i]]=dist[k]+c[i];
if(!vis[u[i]])
{
if(++cnt[u[i]]==n)
return;
q.push(u[i]);
vis[u[i]]=1;
}
}
}
}
return;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
e=0;
memset(vis,0,sizeof(vis));
memset(cnt,0,sizeof(cnt));
memset(head,-1,sizeof(head));
memset(pre,-1,sizeof(pre));
scanf("%d%d",&n,&m);
for(int i=0;i<m;i++)
{
scanf("%d%d%d",&u[i],&v[i],&c[i]);
addage(u[i],v[i],c[i]);
}
LL sum=0;
spfa1(1);
for(int i=2;i<=n;i++)
{
sum+=dist[i];
}
//printf("%d\n",sum);
turn();
memset(vis,0,sizeof(vis));
memset(cnt,0,sizeof(cnt));
spfa2(1);
for(int i=2;i<=n;i++)
{
sum+=dist[i];
}
printf("%lld\n",sum);
}
return 0;
}
POJ 1511 Invitation Cards
最新推荐文章于 2018-08-13 15:34:19 发布