vijos1423最佳路線——有向圖最小環模板
阿新 • • 發佈:2018-11-10
題目:vijos1423.
題目大意:給定一些單向直道與彎道,並且給出每條單向直道連線哪兩條彎道,讓你求出經過彎道1的邊權最小的環.
這道題我們可以將彎道看成點,將直道看成有向邊,那麼原問題其實就是求經過點1的最小環.
解決最小環問題一般用的是floyd演算法或dijkstra演算法,這裡就給出一種堆優化dijkstra演算法解決這個問題.
首先我們可以想到,先將1定為原點,然後將1的距離定為0,1出堆後就將1的距離打上INF,然後知道下一次更新1的距離時,這個距離就是最小環的大小.
這種做法的正確性應該比較顯然.
程式碼如下:
#include<bits/stdc++.h> using namespace std; #define Abigail inline void typedef long long LL; const int N=200,M=100000,INF=(1<<29)-1; int n,m; int dis[N+9],use[N+9],v[N+9]; struct node{ int x,v; node(int xx,int vv){x=xx;v=vv;} bool operator > (const node &p)const{return v>p.v;} }; priority_queue<node,vector<node>,greater<node> >q; struct side{ int y,next,v; }e[M*2+9]; int lin[N+9],top; void ins(int x,int y,int z){ e[++top].y=y;e[top].v=z;e[top].next=lin[x];lin[x]=top; } void dijkstra(int s){ for (int i=1;i<=n;i++) dis[i]=INF; int diss=INF; dis[s]=0; for (int i=lin[s];i;i=e[i].next) if (e[i].y==s){ //處理自環問題 if (diss>e[i].v+v[e[i].y]) diss=e[i].v+v[s]; }else if (dis[s]+e[i].v+v[e[i].y]<dis[e[i].y]){ dis[e[i].y]=dis[s]+e[i].v+v[e[i].y]; q.push(node(e[i].y,dis[e[i].y])); } dis[s]=INF; while (!q.empty()){ int t=q.top().x;q.pop(); if (use[t]) continue; use[t]=1; for (int i=lin[t];i;i=e[i].next) if (dis[t]+e[i].v+v[e[i].y]<dis[e[i].y]){ dis[e[i].y]=dis[t]+e[i].v+v[e[i].y]; q.push(node(e[i].y,dis[e[i].y])); } } if (diss<dis[s]) dis[s]=diss; } Abigail into(){ scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) scanf("%d",&v[i]); int x,y,z; for (int i=1;i<=m;i++){ scanf("%d%d%d",&x,&y,&z); ins(x,y,z); } } Abigail work(){ dijkstra(1); } Abigail outo(){ if (dis[1]>INF>>1) puts("-1"); else printf("%d\n",dis[1]); } int main(){ into(); work(); outo(); return 0; }