题意:n个点的无向带权图,上面有f个消防站,现在要添加一个消防站,求一个最好且最小的标号的方法,使得原图中每个点到它最近的消防站的距离中的最大值要最小。
题解:1、以f个消防站所在位置为起点,做一次spfa求出它们到其他所有点的最小距离。
2、枚举每个点,从该点出发求一次spfa求出它到所有点的距离。在该点放消防站的代价就是max(所有的i=>min(d[i],dist[i]))。
3、PS:消防站可能一开始就遍布整个图,即,每个点都有消防站,此时,理论上是不用放的,但是ZF钱太多,还是要建一座,就是第1座,所以枚举是要赋初值= =!。
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<queue> 5 using namespace std; 6 const int N=5050,inf=10000; 7 int head[N],nc,n; 8 struct Edge 9 { 10 int to,next,cost; 11 }edge[100000]; 12 void add(int a,int b,int c) 13 { 14 edge[nc].to=b;edge[nc].next=head[a];edge[nc].cost=c;head[a]=nc++; 15 edge[nc].to=a;edge[nc].next=head[b];edge[nc].cost=c;head[b]=nc++; 16 } 17 int dist[N]; 18 int stk[N],f,r; 19 bool vis[N]; 20 void fire_spfa(int fire[],int num) 21 { 22 memset(vis,false,sizeof(vis)); 23 f=r=0; 24 for(int i=0;i<num;i++) 25 { 26 int t=fire[i]; 27 if(!vis[t]) 28 { 29 vis[t]=true; 30 dist[stk[r++]=t]=0; 31 } 32 } 33 while(f!=r) 34 { 35 int now=stk[f++]; 36 if(f==N)f=0; 37 vis[now]=false; 38 for(int i=head[now];i!=-1;i=edge[i].next) 39 { 40 int to=edge[i].to,cc=edge[i].cost; 41 if(dist[to]>dist[now]+cc) 42 { 43 dist[to]=dist[now]+cc; 44 if(!vis[to]) 45 { 46 stk[r++]=to; 47 if(r==N)r=0; 48 vis[to]=true; 49 } 50 } 51 } 52 } 53 } 54 int new_spfa(int src) 55 { 56 memset(vis,false,sizeof(vis)); 57 f=0,r=1; 58 vis[src]=true; 59 int d[N]; 60 for(int i=1;i<=n;i++) 61 d[i]=inf; 62 d[src]=0; 63 stk[0]=src; 64 while(f!=r) 65 { 66 int now=stk[f++]; 67 if(f==N)f=0; 68 vis[now]=false; 69 for(int i=head[now];i!=-1;i=edge[i].next) 70 { 71 int to=edge[i].to; 72 int cc=edge[i].cost; 73 if(d[to]>d[now]+cc) 74 { 75 d[to]=d[now]+cc; 76 if(!vis[to]) 77 { 78 stk[r++]=to; 79 vis[to]=true; 80 if(r==N)r=0; 81 } 82 } 83 } 84 } 85 int ans=0; 86 for(int i=1;i<=n;i++) 87 { 88 ans=max(ans,min(d[i],dist[i])); 89 } 90 return ans; 91 } 92 int main() 93 { 94 int ff,fire[N],a,b,c; 95 memset(head,-1,sizeof(head)); 96 nc=0; 97 scanf("%d%d",&ff,&n); 98 for(int i=0;i<ff;i++) 99 scanf("%d",fire+i); 100 while(scanf("%d%d%d",&a,&b,&c)!=EOF) 101 add(a,b,c); 102 for(int i=1;i<=n;i++) 103 dist[i]=inf; 104 fire_spfa(fire,ff); 105 int id=1,ans=inf; 106 for(int i=1;i<=n;i++) 107 { 108 if(dist[i]!=0) 109 { 110 int tp=new_spfa(i); 111 if(ans>tp) 112 { 113 ans=tp; 114 id=i; 115 } 116 } 117 } 118 printf("%d\n",id); 119 return 0; 120 }