---恢复内容开始---
http://poj.org/problem?id=1511
一个spfa类的模板水题。
题意:就是求从1到n个点的来回的所有距离和。
对spfa类的题还是不太熟练,感觉还是做少了,多水水这种题。
思路:也就是双向的spfa就行了。这里就是注意答案要用long long 类型来存就可以。
#include <stdio.h>
#include <string.h>
#include <queue>
#define maxn 1000010
#define inf 0x3f using namespace std; int m,n,pos,a[ maxn ],b[ maxn ],c[ maxn ],head[ maxn ]; long long ans , dist[ maxn ]; bool vis[ maxn ]; struct note {
int v,w,next;
}edge[maxn]; void init()
{
pos = ;
memset( dist , inf , sizeof( dist ) );
memset( head , - , sizeof( head ) );
memset( vis , false ,sizeof( vis ) );
} void add(int x,int v,int w) //这是用数组来构建的一个邻接表。不懂可以在纸上模拟一次就行。
{
edge[ pos ].v = v;
edge[ pos ].w = w;
edge[ pos ].next = head[ x ];
head[ x ] = pos++;
} void spfa() //标准的spfa模板。如果可能有负权回路的话,那就加个num数组来判断。
{
queue<int >s;
s.push();
vis[ ] = true;
dist[ ] = ;
while(!s.empty())
{
int tmp = s.front();
s.pop();
vis [ tmp ] = false;
for( int i = head[ tmp ] ; i != - ; i = edge[ i ].next )
{
if( dist[ edge[ i ].v ] > dist[ tmp ] + edge[ i ].w)
{
dist[ edge[ i ].v ] = dist[ tmp ] + edge[ i ].w;
if( !vis[ edge[ i ].v ] )
{
s.push( edge[ i ].v );
vis[ edge[ i ].v ] =true;
} } }
}
for( int i = ; i <= m ; i++ )
ans += dist[ i ];
} int main()
{
// freopen("in.txt","r",stdin);
int t;
scanf("%d",&t);
while(t--)
{
ans = ;
scanf("%d%d",&m,&n);
init(); //两次spfa,正向和反向。
for( int i = ; i <= n ; i++ )
{
scanf("%d%d%d",&a[ i ],&b[ i ],&c[ i ]);
add( a[ i ] , b[ i ] , c[ i ] );
}
spfa();
init();
for( int i = ; i <= n ; i++ )
add( b[ i ] , a[ i ] , c[ i ] );
spfa();
printf("%lld\n",ans);
}
return ;
}