POJ 1511 Invitation Cards dij

分析:正向加边,反向加边,然后两遍dij

#include<cstdio>
#include<cstring>
#include<queue>
#include<cstdlib>
#include<algorithm>
#include<vector>
#include<cmath>
using namespace std;
typedef long long LL;
const int N=1e6+5;
const int INF=0x3f3f3f3f;
struct Edge{
   int u,v,next;
   LL w;
   bool operator<(const Edge &e)const{
      return w>e.w;
   } 
}edge[N],o[N];
int head[N],tot,n,m;
LL d[N],tmp[N];
void add(int u,int v,int w){
   edge[tot].v=v;
   edge[tot].w=w;
   edge[tot].next=head[u];
   head[u]=tot++;
}
priority_queue<Edge>q;
bool vis[N];
void dij(int s){
    for(int i=1;i<=n;++i)d[i]=-1,vis[i]=0;
    d[s]=0,q.push(Edge{0,s,0,0});
    while(!q.empty()){
       while(!q.empty()&&vis[q.top().v])q.pop();
       if(q.empty())break;
       int u=q.top().v;
       q.pop();
       vis[u]=1;
       for(int i=head[u];~i;i=edge[i].next){
          int v=edge[i].v;
          if(!vis[v]&&(d[v]==-1||d[v]>d[u]+edge[i].w)){
            d[v]=d[u]+edge[i].w;
            q.push(Edge{0,v,d[v],0});
          }
       } 
    }
    // return d[t];
}
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
    scanf("%d%d",&n,&m);
    memset(head,-1,sizeof(head)),tot=0;
    for(int i=1;i<=m;++i){
       scanf("%d%d%I64d",&o[i].u,&o[i].v,&o[i].w);
       add(o[i].u,o[i].v,o[i].w); 
    }
    dij(1);
    for(int i=1;i<=n;++i)tmp[i]=d[i];
    memset(head,-1,sizeof(head)),tot=0;
    for(int i=1;i<=m;++i){
       add(o[i].v,o[i].u,o[i].w); 
    }
    dij(1);
    LL ans=0;
    for(int i=1;i<=n;++i)
      ans+=tmp[i]+d[i];
    printf("%I64d
",ans);
    }   
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/shuguangzw/p/5319629.html