poj 1511 Invitation Cards(2遍spfa)

来源:互联网 发布:soc软件品牌 编辑:程序博客网 时间:2024/06/05 05:44

题目地址

题目大意:n个站,告诉站之间的权值,求从1到所有点并返回1的最小权值和

解题思路:对1进行单源spfa,返回的时候因为spfa只能单源,所以将原图转置,再对1进行一次spfa,图的转置需要特殊处理,我采用的是邻接表存储图,相当于建了2个图

#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <cmath>#include <algorithm>#include <queue>#include <stack>#include <vector>using namespace std;const int maxn = 1000000+10;const int INF = 0xfffffff;int dis[maxn],head[maxn],vis[maxn],cnt,n,m;int u[maxn],v[maxn],w[maxn];struct Edge{    int to,next,w;}e[maxn];void addEdge(int u,int v,int w){    e[cnt].to = v;    e[cnt].w = w;    e[cnt].next = head[u];    head[u] = cnt++;}void spfa(){    queue<int> q;    while(!q.empty())   q.pop();    memset(vis,0,sizeof(vis));    for(int i = 1; i <= n; i++)        dis[i] = INF;    q.push(1);    vis[1] = 1;    dis[1] = 0;    while(!q.empty())    {        int v = q.front();        q.pop();        vis[v] = 0;        for(int i = head[v]; i != -1; i = e[i].next)        {            if(dis[e[i].to] > dis[v]+e[i].w)            {                dis[e[i].to] = dis[v]+e[i].w;                if(!vis[e[i].to])                {                    vis[e[i].to] = 1;                    q.push(e[i].to);                }            }        }    }}void graph1(){    cnt = 1;    memset(head,-1,sizeof(head));    for(int i = 1; i <= m; i++)        addEdge(u[i],v[i],w[i]);}void graph2(){    cnt = 1;    memset(head,-1,sizeof(head));    for(int i = 1; i <= m; i++)        addEdge(v[i],u[i],w[i]);}int main(){    int t,sum;    scanf("%d",&t);    while(t--)    {        scanf("%d%d",&n,&m);        for(int i = 1; i <= m; i++)        {            scanf("%d%d%d",&u[i],&v[i],&w[i]);        }        sum = 0;        graph1();        spfa();        for(int i = 2; i <= n; i++)            sum += dis[i];        graph2();        spfa();        for(int i = 2; i <= n; i++)            sum += dis[i];        printf("%d\n",sum);    }return 0;}



0 0
原创粉丝点击