题目链接:http://218.28.220.249:50015/JudgeOnline/problem.php?id=1262
分析:类似于最短路,每次更新第a种宝石和第b种宝石,可以合成一个第c种宝石的魔力值,由于点的数目比较多,我们可以采用邻接表存图的,用SPFA来更新。
一直不知道该如何去存图,其实和原本的套路差不多,只是写法稍微改了一点,具体分析看代码吧。
CODE:
#include<stdio.h>
#include<algorithm>
#include<iostream>
#include<string.h>
#include<vector>
#include<stdlib.h>
#include<queue>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn=100005;
int dis[maxn],vis[maxn],head[maxn];
int tot;
struct node
{
int v,w,next;
}eg[maxn*2];
void addedge(int u,int v,int w)//邻接表存图
{
eg[tot].v=v;
eg[tot].w=w;
eg[tot].next=head[u];
head[u]=tot++;
}
queue<int>q;
void spfa()
{
while(!q.empty())
{
int u=q.front();
q.pop();
vis[u]=0;
for(int i=head[u]; i!=-1; i=eg[i].next)
{
int v=eg[i].v;
int w=eg[i].w;
if(dis[w]>dis[u]+dis[v])//能用u、v合成w,且需要的魔力值更小
{
dis[w]=dis[u]+dis[v];
if(!vis[w])
{
vis[w]=1;
q.push(w);
}
}
}
}
}
void init()
{
memset(head,-1,sizeof(head));
tot=0;
while(!q.empty())
q.pop();
}
int main()
{
int t,n,m;
scanf("%d",&t);
while(t--)
{
init();
memset(dis,INF,sizeof(dis));
memset(vis,0,sizeof(vis));
scanf("%d%d",&n,&m);
for(int i=1; i<=n; i++)
scanf("%d",&dis[i]);//先直接存进去,后面再更新
int x,y,z;
for(int i=0; i<m; i++)
{
scanf("%d%d%d",&x,&y,&z);
addedge(x,y,z);
addedge(y,x,z);
if(!vis[x])//有需要x,y合成的宝石,放入队列,为了更新是否有最小的,并标记
{
q.push(x);
vis[x]=1;
}
if(!vis[y])
{
q.push(y);
vis[y]=1;
}
}
spfa();
for(int i=1;i<=n;i++)
{
if(i!=1)
printf(" ");
printf("%d",dis[i]);
}
printf("\n");
}
}
比赛的时候一直在卡水题,这道题还没来得及仔细思考,还是挺遗憾的。。。