zoukankan      html  css  js  c++  java
  • POJ 1511 Invitation Cards(Dijkstra(优先队列)+SPFA(邻接表优化))

    题目链接:http://poj.org/problem?id=1511

    题目大意:给你n个点,m条边(1<=n<=m<=1e6),每条边长度不超过1e9。问你从起点到各个点以及从各个点到起点的最小路程总和。

    解题思路:这里用了优先队列优化的dijkstra复杂度mlogn,从起点到个点最短路径直接算就好了,算各个点到起点的最短路径,只要把边的方向反一下,再算一次从起点到个点最短路径就好了。

    Dijkstra:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<functional>
     5 #include<vector>
     6 #include<queue>
     7 using namespace std;
     8 typedef long long LL;
     9 typedef pair<int,int> p;
    10 const int N=1e6+5;
    11 const int INF=1<<30;//这里不能比1e9小 
    12 struct edge{
    13     int to,cost;
    14 };
    15 
    16 vector<edge>eg[N];
    17 int V,E;
    18 bool used[N];
    19 int d[N];
    20 int a[N],b[N],c[N];
    21 
    22 void dijkstra(int s){
    23     for(int i=1;i<=V;i++){
    24         d[i]=INF;
    25         used[i]=false;
    26     }
    27     d[s]=0;
    28     
    29     priority_queue<p,vector<p>,greater<p> >q;
    30     q.push(p(0,s));
    31     while(!q.empty()){
    32         p p1=q.top();
    33         q.pop();
    34         int v=p1.second;
    35         if(used[v])    continue;
    36         used[v]=true;
    37         for(int i=0;i<eg[v].size();i++){
    38             edge e=eg[v][i];
    39             if(d[e.to]>d[v]+e.cost){
    40                 d[e.to]=d[v]+e.cost;
    41                 q.push(p(d[e.to],e.to));
    42             }
    43         }
    44     }
    45 } 
    46 
    47 int main(){
    48     int q;
    49     scanf("%d",&q);
    50     while(q--){
    51         scanf("%d %d",&V,&E);
    52         for(int i=1;i<=V;i++){
    53             eg[i].clear();
    54         }
    55         for(int i=1;i<=E;i++){
    56             scanf("%d%d%d",&a[i],&b[i],&c[i]);
    57             edge gg;
    58             gg.to=b[i],gg.cost=c[i];
    59             eg[a[i]].push_back(gg);
    60         }
    61         dijkstra(1);
    62         LL sum=0;
    63         for(int i=1;i<=V;i++){
    64             sum+=d[i];
    65         }
    66         //将边的方向反一下
    67         for(int i=1;i<=V;i++){
    68             eg[i].clear();
    69         }
    70         for(int i=1;i<=E;i++){
    71             edge gg;
    72             gg.to=a[i],gg.cost=c[i];
    73             eg[b[i]].push_back(gg);
    74         }
    75         dijkstra(1);
    76         for(int i=1;i<=V;i++){
    77             sum+=d[i];
    78         }
    79         printf("%lld
    ",sum);
    80     }
    81 }

     SPFA:

     1 #include<iostream>
     2 #include<queue>
     3 #include<vector>
     4 using namespace std;
     5 const int INF=1<<30;
     6 const int N=1e6+5;
     7 
     8 struct edge{
     9     int to,cost;
    10 }; 
    11 
    12 vector<edge>eg[N];
    13 int V,E;
    14 bool used[N];//是否在队列中 
    15 int d[N];
    16 int a[N],b[N],c[N];
    17 
    18 void spfa(int s){
    19     for(int i=1;i<=V;i++){
    20         d[i]=INF;
    21         used[i]=false;
    22     }
    23     d[s]=0;
    24     
    25     queue<int>q;
    26     q.push(s);
    27     used[s]=true; 
    28     while(!q.empty()){
    29         int v=q.front();
    30         q.pop();
    31         used[v]=false;
    32         for(int i=0;i<eg[v].size();i++){
    33             edge e=eg[v][i];
    34             if(d[e.to]>d[v]+e.cost){
    35                 d[e.to]=d[v]+e.cost;
    36                 if(!used[e.to]){
    37                     used[e.to]=true;
    38                     q.push(e.to);
    39                 }
    40             }
    41         }
    42     }    
    43 } 
    44 
    45 int main(){
    46     int q;
    47     scanf("%d",&q);
    48     while(q--){
    49         scanf("%d%d",&V,&E);
    50         for(int i=1;i<=V;i++){
    51             eg[i].clear();
    52         }
    53         for(int i=1;i<=E;i++){
    54             scanf("%d%d%d",&a[i],&b[i],&c[i]);
    55             edge gg;
    56             gg.to=b[i],gg.cost=c[i];
    57             eg[a[i]].push_back(gg);
    58         }
    59         spfa(1);
    60         long long sum=0;
    61         for(int i=1;i<=V;i++){
    62             sum+=d[i];
    63         }
    64         //方向反一下 
    65         for(int i=1;i<=V;i++){
    66             eg[i].clear();
    67         }
    68         for(int i=1;i<=E;i++){
    69             edge gg;
    70             gg.to=a[i],gg.cost=c[i];
    71             eg[b[i]].push_back(gg);
    72         }
    73         spfa(1);
    74         for(int i=1;i<=V;i++){
    75             sum+=d[i];
    76         }
    77         printf("%lld
    ",sum);
    78     }
    79 }
  • 相关阅读:
    重谈MST及Kruskal算法
    小技巧—边权转点权
    JDOJ 1062 过路费
    总结—二分答案求解问题
    CF10D LCIS
    NOIP 2012 摆花
    SDOI 2014 旅行
    CF550C Divisibility by Eight
    CF295C Greg and Friends
    USACO Closing the Farm
  • 原文地址:https://www.cnblogs.com/fu3638/p/6980479.html
Copyright © 2011-2022 走看看