CCF 交通规划

来源:互联网 发布:crm系统源码 编辑:程序博客网 时间:2024/04/29 04:47

题意大致如下:给你一张无向带权图,有标号为1到n的节点,现在要你选择一些边留下来,使得在留下来的边构成的新的图里,每个节点到节点1的最小距离不变(即和初始图一样),在满足上述要求的前提下,要使留下来的边的权重和最小,并求出这个最小权重和。

题解:只要我们用dijsktra算法加以改造遍历一遍原图,就能解决这个问题。而本题与一般的dijsktra模板题不同的地方在于,一般dijsktra只是求出源点到其他个点的最短距离,但并不考虑和记录路径,但本题要求的是权重和的最小值,也就是说我们要知道的是最后我们选择了哪些边留下来,或者说我们要知道留下来的所有边的权重是多少。为此,我建立了一个结构体叫Node,它有成员dist和cost,dist是表示它到源点的最小距离,而cost是表示为了使它和源点联通的最小花费(这个联通要保证是最短距离的前提下)。至于更新,dist更新和正常dijsktra更新时一样,先找到一个目前没有被加入集合的dist最小的节点u,然后用u来更新周边节点的dist,cost更新则是随着dist的更新进行的(如此保证这个cost满足最小距离这个前提),并且这个cost应该就等于节点u和被更新节点v的边的权重,即有Node[v].cost=weight[u][v]。最后,要注意的就是,有些节点的最短路径可能不止一条,而且,这些节点被开始的u节点更新得到的cost会要比后面的u节点更新得到的cost要大,所以当有Node[v].dist==Node[u].dist+weight[u][v]时,要注意更新Node[v].cost。(根据题目范围,dijkstra算法应用优先队列进行优化)

输入: 两个整数n,m。n是节点数,m是边数。就下来m行,每行三个数u,v,w,代表节点u,v之间有一条权重为w的边。

输出:一个整数,最小权重和。

代码如下:

#include<iostream>#include<cmath>#include<cstdio>#include<cstring>#include<string>#include<queue>using namespace std;const int maxn=10100;const int maxm=101010;const int inf=0x08080808;int n,m;int head[maxn],icount,vis[maxn];struct Edge{    int v,w;    int next;}edge[maxm*2];struct Node{   int dist;   int cost;}node[maxn];struct Dist{    int dist;    int num;    bool operator <(const Dist& a)const {        return dist>a.dist;    }};priority_queue<Dist> pq;void insert_edge(int u,int v,int w){    edge[icount].v=v;    edge[icount].w=w;    edge[icount].next=head[u];    head[u]=icount++;}void Dij(int s){    for(int i=1;i<=n;++i){        node[i].dist=node[i].cost=inf;        vis[i]=0;    }    Dist temp={0,s};    node[s].dist=node[s].cost=0;    pq.push(temp);    for(int i=1;i<n;++i){        temp=pq.top();        while(vis[temp.num]){            pq.pop();            temp=pq.top();        }        s=temp.num;        for(int j=head[s];j!=-1;j=edge[j].next){            int v=edge[j].v,w=edge[j].w;            if((node[s].dist+w)<=node[v].dist){                node[v].dist=node[s].dist+w;                temp.num=v;                temp.dist=node[v].dist;                pq.push(temp);                if(w<node[v].cost)                    node[v].cost=w;            }        }        vis[s]=1;    }}int main(){    int u,v,w;    icount=0;    scanf("%d%d",&n,&m);    for(int i=1;i<=n;++i)        head[i]=-1;    for(int i=0;i<m;++i){        scanf("%d%d%d",&u,&v,&w);        insert_edge(u,v,w);        insert_edge(v,u,w);    }    Dij(1);    int ans=0;    for(int i=1;i<=n;++i){        ans+=node[i].cost;    }    printf("%d\n",ans);    return 0;}

0 0
原创粉丝点击