这个题很有意思,其实就是求出最短路径,再用最短路径值*结点值的和。通过这题,又找到了编程的一个bug,总是想省空间,结果就只能悲剧了,还是先相乘后强制转化的问题,必须出错的!第一次用比__int64还大的数据类型usigned long long,另外熟悉了一下宏,感觉还不错。对最短路径又有了新的想法,理解算法很有好处啊!!
#include<iostream>
#include<queue>
#define MAXN 50005
#define ULL unsigned long long
#define INF 184467440737095516151
using namespace std;struct Node
{int v;ULL price;Node *next;
}Edge[MAXN<<1],*ptr[MAXN];int N,E,EdgeNum;
ULL dist[MAXN];void addEdge( int u,int v,ULL price )
{Node *p=&Edge[EdgeNum++];p->v=v;p->price=price;p->next=ptr[u];ptr[u]=p;
}
bool inQ[MAXN];
bool changed[MAXN];
void SPFA()
{memset( changed,0,sizeof(changed) );memset( inQ,0,sizeof(inQ) );memset( dist,0xFF,sizeof(dist) );dist[1]=0;queue<int>myQueue;myQueue.push(1);while( !myQueue.empty() ){int u=myQueue.front();myQueue.pop();Node *p=ptr[u];inQ[u]=false;while( p ){if( dist[p->v]>dist[u]+p->price ){dist[p->v]=dist[u]+p->price;changed[p->v]=true;if( !inQ[p->v] ){inQ[p->v]=true;myQueue.push(p->v);}}p=p->next;}}
}int main()
{int degree[MAXN];int i,j;int T;scanf( "%d",&T );while( T-- ){EdgeNum=0;scanf( "%d %d",&N,&E );for( i=1;i<=N;i++ )ptr[i]=NULL;for( i=1;i<=N;i++ )scanf( "%d",°ree[i] );int u,v;ULL price;for( i=1;i<=E;i++ ){scanf( "%d %d %llu",&u,&v,&price );addEdge( u,v,price );addEdge( v,u,price );}SPFA();unsigned long long ans=0;for( i=2;i<=N;i++ )if( changed[i]==false ){printf( "No Answer\n" );goto BY;}for( i=2;i<=N;i++ )ans+=dist[i]*degree[i];printf( "%llu\n",ans );BY:; }return 0;
}