[洛谷1342]请柬
题目大意:
给定一个起点,求以其余所有点分别为必经点的最短回路之和。
思路:
建立反向图,在正反图上分别跑一遍Dijkstra,最后求和即可。
注意数据规模,要开long long不然会WA,只能拿25分。
1 #include<cstdio> 2 #include<cctype> 3 #include<vector> 4 #include<ext/pb_ds/priority_queue.hpp> 5 inline int getint() { 6 register char ch; 7 while(!isdigit(ch=getchar())); 8 register int x=ch^'0'; 9 while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0'); 10 return x; 11 } 12 const long long inf=0x7fffffffffffffff; 13 const int V=1000001; 14 struct Edge { 15 int to; 16 long long w; 17 }; 18 std::vector<Edge> e1[V],e2[V]; 19 inline void add_edge(std::vector<Edge> *e,const int u,const int v,const long long w) { 20 e[u].push_back((Edge){v,w}); 21 } 22 struct Vertex { 23 int id; 24 long long dis; 25 bool operator > (const Vertex &another) const { 26 return dis>another.dis; 27 } 28 }; 29 int n; 30 long long dis1[V],dis2[V]; 31 __gnu_pbds::priority_queue<Vertex,std::greater<Vertex> > q; 32 __gnu_pbds::priority_queue<Vertex,std::greater<Vertex> >::point_iterator p[V]; 33 const int s=1; 34 inline void Dijkstra(long long *dis,std::vector<Edge> *e) { 35 q.clear(); 36 for(register int i=1;i<=n;i++) { 37 p[i]=q.push((Vertex){i,dis[i]=(i==s)?0:inf}); 38 } 39 while(q.top().dis!=inf) { 40 int x=q.top().id; 41 for(register unsigned i=0;i<e[x].size();i++) { 42 Edge &y=e[x][i]; 43 if(dis[x]+y.w<dis[y.to]) { 44 q.modify(p[y.to],(Vertex){y.to,dis[y.to]=dis[x]+y.w}); 45 } 46 } 47 q.modify(p[x],(Vertex){x,inf}); 48 } 49 } 50 int main() { 51 n=getint(); 52 for(register int m=getint();m;m--) { 53 int u=getint(),v=getint(); 54 long long w=getint(); 55 add_edge(e1,u,v,w); 56 add_edge(e2,v,u,w); 57 } 58 Dijkstra(dis1,e1); 59 Dijkstra(dis2,e2); 60 long long ans=0; 61 for(register int i=2;i<=n;i++) { 62 ans+=dis1[i]+dis2[i]; 63 } 64 printf("%lld\n",ans); 65 return 0; 66 }