随笔 - 843,  文章 - 0,  评论 - 214,  阅读 - 38万

POJ_3013

    如果按题目中的计算方法去想的话,是很难想到合适的算法的,而如果换个角度考虑问题的就海阔天空了。

    题目中是以边为中心去考虑的,如果我们以点为中心去考虑,最后的结果就是各点的点权和该点到根的边权和相乘之后再求和即可,于是只要根到每个点途径的边权和最小就行了,那么自然就是最短路了。

复制代码
#include<stdio.h>
#include<string.h>
#define MAXD 50010
#define MAXM 100010
#define INF 1000000000000000ll
int N, M, D, a[MAXD], inq[MAXD], q[MAXD], first[MAXD], next[MAXM], v[MAXM], w[MAXM], e;
long long int d[MAXD];
void add(int x, int y, int z)
{
v[e] = y, w[e] = z;
next[e] = first[x];
first[x] = e;
++ e;
}
void init()
{
int i, j, x, y, z;
memset(first + 1, -1, sizeof(first[0]) * N);
e = 0;
for(i = 1; i <= N; i ++)
scanf("%d", &a[i]);
for(i = 0; i < M; i ++)
{
scanf("%d%d%d", &x, &y, &z);
add(x, y, z), add(y, x, z);
}
}
void solve()
{
int i, j, k, front, rear, x;
long long int ans;
for(i = 1; i <= N; i ++)
d[i] = INF;
d[1] = 0;
front = rear = 0;
q[rear ++] = 1;
memset(inq + 1, 0, sizeof(inq[0]) * N);
while(front != rear)
{
x = q[front ++];
if(front > N)
front = 0;
inq[x] = 0;
for(i = first[x]; i != -1; i = next[i])
if(d[x] + w[i] < d[v[i]])
{
d[v[i]] = d[x] + w[i];
if(!inq[v[i]])
{
inq[v[i]] = 1;
q[rear ++] = v[i];
if(rear > N)
rear = 0;
}
}
}
ans = 0;
for(i = 2; i <= N; i ++)
{
if(d[i] == INF)
{
printf("No Answer\n");
return ;
}
ans += a[i] * d[i];
}
printf("%lld\n", ans);
}
int main()
{
int t;
scanf("%d", &t);
while(t --)
{
scanf("%d%d", &N, &M);
init();
if(N == 0)
printf("0\n");
else
solve();
}
return 0;
}
复制代码


posted on   Staginner  阅读(188)  评论(0编辑  收藏  举报
努力加载评论中...
< 2012年3月 >
26 27 28 29 1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
1 2 3 4 5 6 7

点击右上角即可分享
微信分享提示