codeforces 938d D. Buy a Ticket
阿新 • • 發佈:2018-12-14
題意: n個點 m 個邊,並且每個點有個權值,你要對每個點求出 一個點j 使得dis[i,j]*2+a[j] 是最小的。
思路: 建立一個超級源點 S 從S 向每個點建一條邊 邊權為該點的點權,然後跑個dij 就是答案。 不難理解。
程式碼:
#include<bits/stdc++.h> using namespace std; typedef long long ll; const ll inf =1e18+5; typedef pair< ll,int > pli; const int N = 2e5+5; ll dis[N]; int vis[N]; ll a[N]; int n,m; //int S; vector< pli >ve[N]; void dij() { priority_queue< pli, vector<pli> ,greater< pli > >q; for(int i=1;i<=n;i++) { dis[i]=a[i]; vis[i]=0; q.push(pli(a[i],i)); } while(!q.empty()) { pli tmp=q.top(); q.pop(); int u=tmp.second; if(tmp.first>dis[u]) continue; vis[u]=1; for(int i=0;i<ve[u].size();i++) { int v=ve[u][i].second; if(vis[v]) continue; if(dis[v]>dis[u]+ve[u][i].first) { dis[v]=dis[u]+ve[u][i].first; q.push(pli(dis[v],v)); } } } for(int i=1;i<=n;i++) { printf("%lld ",dis[i]); } } void dij(int S) { for(int i=0;i<=n+2;i++) { dis[i]=inf; vis[i]=0; } dis[0]=0; priority_queue< pli, vector<pli>, greater<pli> >q; q.push(pli(0,S)); while(!q.empty()) { pli tmp=q.top(); q.pop(); int u=tmp.second; if(tmp.first>dis[u]) continue; vis[u]=1; for(int i=0;i<ve[u].size();i++) { int v=ve[u][i].second; if(vis[v]) continue; if(dis[v]>dis[u]+ve[u][i].first) { dis[v]=dis[u]+ve[u][i].first; q.push(pli(dis[v],v)); } } } for(int i=1;i<=n;i++) { printf("%lld ",dis[i]); } } int main() { int u,v; ll w; scanf("%d %d",&n,&m); for(int i=1;i<=m;i++) { scanf("%d %d %lld",&u,&v,&w); ve[u].push_back(pli(w*2,v)); ve[v].push_back(pli(w*2,u)); } for(int i=1;i<=n;i++) { scanf("%lld",&a[i]); ve[0].push_back(pli(a[i],i)); } dij(0); return 0; }