POJ 3013 最短路变形 0.0

来源:互联网 发布:纵横家 知大局 编辑:程序博客网 时间:2024/06/06 23:55

题意:给你一个无向图,让你找到一棵以1为根的树,使所有边的权值和最小。边的权值和是这样定义的:所有子节点的weight*这条边的”单价“。

思路:初一看没没什么思路,但是转换下思路可以用最短路做= =。最终我们会得到一棵树,每条边的权值转移到点上就是这个点走到1节点的最短路*这个点的weight,这样就保证了结果最小。

代码:

#include<cstdio>#include<cstring>#include<iostream>#include<queue>using namespace std;#define ll long longconst int maxn = 50010;const int inf = 0x3f3f3f3f;struct Side{    int v,next;    ll w;}side[maxn*2];int node[maxn],top;void add_side(int u,int v,ll w){    side[top] = (Side){v,node[u],w};node[u] = top ++;    side[top] = (Side){u,node[v],w};node[v] = top ++;}int nn,vis[maxn],mon[maxn];ll dis[maxn];void dfs(int u){    vis[u] = 1;    nn ++;    for(int i = node[u];i != -1;i = side[i].next){        int v = side[i].v;        if(vis[v])continue;        dfs(v);    }}queue<int>q;void spfa(int s){    memset(dis,inf,sizeof(dis));    memset(vis,0,sizeof(vis));    dis[s] = 0;    q.push(s);    while(!q.empty()){        int u = q.front();q.pop();        vis[u] = 0;        for(int i = node[u];i != -1;i = side[i].next){            int v = side[i].v;            if(dis[v] > dis[u] + side[i].w){                dis[v] = dis[u] + side[i].w;                if(!vis[v]){                    vis[v] = 1;                    q.push(v);                }            }        }    }}int main(){    //freopen("in.txt","r",stdin);    int T;    scanf("%d",&T);    while(T--){        memset(node,-1,sizeof(node));        top = 0;        int n,m;        scanf("%d%d",&n,&m);        for(int i = 1;i <= n;i ++)            scanf("%d",&mon[i]);        while(m--){            int u,v;            ll w;            scanf("%d%d%lld",&u,&v,&w);            add_side(u,v,w);        }        nn = 0;        memset(vis,0,sizeof(vis));        dfs(1);        if(nn < n){            printf("No Answer\n");            continue;        }        spfa(1);        ll ans = 0;        for(int i = 1;i <= n;i ++){            ans += dis[i] * mon[i];        }        printf("%lld\n",ans);    }    return 0;}


0 0
原创粉丝点击