[USACO3.2]Sweet Butter
题目大意:
给定一张$k$个结点,$m$条边的无向图,其中有$n$个点被标记,在这$k$个点中找出一个点使得这个点到那$n$个点的最短距离之和最小,求出这个距离和。
思路:
对于每个标记结点跑最短路,最后枚举每个结点,求出其到各个标记结点的最短距离和,取$min$。
1 #include<cstdio> 2 #include<cctype> 3 #include<functional> 4 #include<ext/pb_ds/priority_queue.hpp> 5 inline int getint() { 6 char ch; 7 while(!isdigit(ch=getchar())); 8 int x=ch^'0'; 9 while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0'); 10 return x; 11 } 12 const int inf=0x7fffffff; 13 const int V=801; 14 struct Edge { 15 int to,w; 16 }; 17 std::vector<Edge> e[V]; 18 inline void add_edge(const int u,const int v,const int w) { 19 e[u].push_back((Edge){v,w}); 20 } 21 struct Vertex { 22 int id,dis; 23 bool operator > (const Vertex &another) const { 24 return dis>another.dis; 25 } 26 }; 27 int k; 28 int dis[V][V]; 29 __gnu_pbds::priority_queue<Vertex,std::greater<Vertex> > q; 30 __gnu_pbds::priority_queue<Vertex,std::greater<Vertex> >::point_iterator p[V]; 31 inline void Dijkstra(const int s,int *dis) { 32 q.clear(); 33 for(int i=1;i<=k;i++) { 34 p[i]=q.push((Vertex){i,dis[i]=(i==s)?0:inf}); 35 } 36 while(q.top().dis!=inf) { 37 int x=q.top().id; 38 for(unsigned i=0;i<e[x].size();i++) { 39 Edge &y=e[x][i]; 40 if(dis[x]+y.w<dis[y.to]) { 41 q.modify(p[y.to],(Vertex){y.to,dis[y.to]=dis[x]+y.w}); 42 } 43 } 44 q.modify(p[x],(Vertex){x,inf}); 45 } 46 } 47 int main() { 48 int n=getint(); 49 k=getint(); 50 int c=getint(); 51 int cow[n]; 52 for(int i=0;i<n;i++) cow[i]=getint(); 53 while(c--) { 54 int u=getint(),v=getint(),w=getint(); 55 add_edge(u,v,w); 56 add_edge(v,u,w); 57 } 58 for(int i=0;i<n;i++) { 59 Dijkstra(cow[i],dis[i]); 60 } 61 int ans=inf; 62 for(int i=1;i<=k;i++) { 63 int tmp=0; 64 for(int j=0;j<n;j++) { 65 tmp+=dis[j][i]; 66 } 67 ans=std::min(ans,tmp); 68 } 69 printf("%d\n",ans); 70 return 0; 71 }