POJ 1511 Invitation Cards(优先队列最短路)

  • 题意: 有向图,求点1到所有点来回最短路之和
  • 思路: 跑两边最短路,一次正向存边,一次反向存边(相当于把其他点到源点的路倒着走了一遍?)
#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
#include<algorithm>
#include<map>
#define ll long long
#define FOR(i,l,r) for(int i = l ; i <= r ;++i )
#define inf 0x3f3f3f3f
#define EPS (1e-9)
#define ALL(T)  T.begin(),T.end()
#define lson(i)     i<<1
#define rson(i)     (i<<1|1)
using namespace std;

template <class T>
inline bool scan_d(T &ret){
    char c; int sgn;
    if(c = getchar(),c==EOF)    return 0;
    while(c!='-'&&(c<'0'||c>'9'))   c=getchar();
    sgn=(c=='-')?-1:1;
    ret=(c=='-')?0:(c-'0');
    while(c=getchar(),c>='0'&&c<='9')   ret=ret*10+(c-'0');
    ret*=sgn;
    return 1;
}

typedef pair<int,int> pii;
const int maxn = 1e6+10;
int n,m;
int d[maxn],d2[maxn];

struct Edge{
    int to,next,cost;
}edge[2][maxn*2];
int head[2][maxn],tot;
void addEdge(int u,int v,int w){
    edge[0][++tot].to = v;
    edge[0][tot].cost = w;
    edge[0][tot].next = head[0][u];
    head[0][u] = tot;

    edge[1][++tot].to = u;
    edge[1][tot].cost = w;
    edge[1][tot].next = head[1][v];
    head[1][v] = tot;

}

void init(){
    for(int i=1;i<=n;++i){
        d[i] = 0x3fffffff;
        d2[i] = 0x3fffffff;
    }
    memset(head,0,sizeof(head));
    tot = 0;
}

void dijkstra(){
    priority_queue<pii,vector<pii>,greater<pii> > que;
    d[1] = 0;
    que.push(pii(0,1));
    while(!que.empty()){
        pii p = que.top();  que.pop();
        int v = p.second;
        if(d[v]<p.first )    continue;
        for(int i=head[0][v];i;i=edge[0][i].next){
            int u = edge[0][i].to;
            if(d[u] > d[v] + edge[0][i].cost){
                d[u] = d[v] + edge[0][i].cost;
                que.push(pii(d[u],u));
            }
        }
    }
}
void dijkstra2(){
    priority_queue<pii,vector<pii>,greater<pii> > que;
    d2[1] = 0;
    que.push(pii(0,1));
    while(!que.empty()){
        pii p = que.top();  que.pop();
        int v = p.second;
        if(d2[v]<p.first )    continue;
        for(int i=head[1][v];i;i=edge[1][i].next){
            int u = edge[1][i].to;
            if(d2[u] > d2[v] + edge[1][i].cost){
                d2[u] = d2[v] + edge[1][i].cost;
                que.push(pii(d2[u],u));
            }
        }
    }
}
int main(){
    int t;
    scan_d(t);
while(t--){
    scan_d(n);  scan_d(m);
    init();
    int fr,to,w;
    FOR(i,1,m){
        scan_d(fr); scan_d(to); scan_d(w);
        addEdge(fr,to,w);
    }
    dijkstra();
    dijkstra2();
    ll ans = 0;
    
    FOR(i,2,n){
        ans += d[i] + d2[i];
    }
    printf("%lld\n",ans);
}

    return 0;
}


用vector存图会tle,前向星加快读跑了1000ms就过了

题目连接

posted @ 2019-07-30 20:18  新新人類  阅读(295)  评论(0编辑  收藏  举报