感觉很经典的题目,虽然我还是不会做
给n个物品可以直接买,需要花费dis[i],然后再给m个合成方法,两个其他的可以合成一个另外其他的,求得到物品1的最小的花费
最短路的题目,然而一直想不通怎么将合成方法转成边,看了题解都是用了spfa,然后边也是很奇怪
代码
#include <bits/stdc++.h>
using namespace std;
const int N=1e4+50;
const int M=1e6+50;
int dis[N];
struct Edge{
int x,y,next;
}edge[M];
int cnt;
int head[N];
void init(){
cnt=0;
memset(head,-1,sizeof(head));
}
void addEdge(int u,int v,int w){
edge[cnt]=Edge{
v,w,head[u]};
head[u]=cnt++;
edge[cnt]=Edge{
u,w,head[v]};
head[v]=cnt++;
}
int n,m;
int a,b,c;
int inq[N];
int spfa(){
queue<int> q;
for(int i=1;i<=n;i++){
q.push(i);
inq[i]=1;
}
while(!q.empty()){
int now=q.front();
q.pop();
inq[now]=0;
for(int i=head[now];i!=-1;i=edge[i].next){
int v=edge[i].x;
//这里u其实是以前的权值,这里代表now和v可以合成的
int u=edge[i].y;
//松弛
if(dis[v]+dis[now]<dis[u]){
dis[u]=dis[v]+dis[now];
if(!inq[u]){
inq[u]=1;
q.push(u);
}
}
}
}
return dis[1];
}
int main(void){
freopen("dwarf.in","r",stdin);
freopen("dwarf.out","w",stdout);
init();
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&dis[i]);
}
while(m--){
scanf("%d%d%d",&a,&b,&c);
//最关键的建边,将合成的b和c作为边的端点,边的权值不再是单纯的权值
//而是代表了能够合成的边,这样在松弛的时候需要不同的处理
addEdge(b,c,a);
}
int ans=spfa();
printf("%d\n",ans);
return 0;
}