Time Limit: 5000MS | Memory Limit: 65536K | |
Total Submissions: 3680 | Accepted: 1303 |
Description
Input
Output
Sample Input
1 6 2 1 2 10 2 3 10 3 4 10 4 5 10 5 6 10 6 1 10
Sample Output
5
Source
Waterloo local 1999.09.25
题意:在一个n各节点的城市,拥有f座消防站,一些居民因为消防站离他们太远而不满,政府决定新建一座消防站,使距离消防站距离最远居民点尽可能近,同时多个点满足时取最小编号的那个。
思路:flloyd计算出在已有f个消防站情况下,每个居民点离附近最近的消防站距离,再一一枚举各个居民点成为消防站。每次枚举时,收缩其他居民点距消防站最近距离,统计距离最大的,若比没建时要近的话,满足题意,更新ansid。
此题有坑点,若图已建满消防站,根据题意,仍需在节点1新建一座,注意。
代码(据说此题在不同oj数据不同,楼主AC在poj,820ms):
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<queue> #include<map> #include<cmath> #define INF 0x3f3f3f3f using namespace std; const int MAXN=505; int g[MAXN][MAXN],ming[MAXN],da[MAXN],db[MAXN],in[MAXN]; int tmp[MAXN][MAXN]; void floyd(int n) { int k,i,j; for(k=1;k<=n;k++) for(i=1;i<=n;i++) for(j=1;j<=n;j++) g[i][j]=min(g[i][j],g[i][k]+g[k][j]); } int main() { int f,n,m,a,b,c,i,j;char sss[100]; while(~scanf("%d%d",&f,&n)) { memset(in,0,sizeof in); for(i=0;i<f;i++)//将消防站节点存在da【】 { scanf("%d",&da[i]); in[da[i]]=1; } getchar(); int ff=0; for(i=1;i<=n;i++)//将居民点节点存进db【】 { if(!in[i])db[ff++]=i; } if(ff==0)//特判.若图已建满,输出 1 { printf("%d\n",1); continue; } memset(g,INF,sizeof g); for(i=1;i<=n;i++) g[i][i]=0; while(gets(sss)&&strlen(sss)) { sscanf(sss,"%d%d%d",&a,&b,&c); if(c<g[a][b])g[a][b]=g[b][a]=c; } floyd(n); memset(ming,INF,sizeof ming); for(i=0;i<f;i++)//更新个居民点据消防站最近距离 { for(j=0;j<ff;j++) { ming[db[j]]=min(ming[db[j]],g[da[i]][db[j]]); } } int ans=0,ansid=1; for(j=0;j<ff;j++) ans=max(ans,ming[db[j]]);//原有f座基础上最远距离,若不能有更好情况,答案为1,所以ansid赋初值1 for(i=0;i<ff;i++) { int mmin=0; for(j=0;j<ff;j++) if(i!=j)mmin=max(mmin,min(g[db[i]][db[j]],ming[db[j]])); if(mmin<ans)ans=mmin,ansid=db[i];//当ff只有一个,枚举该点时,所有居民点都有一消防站,mmin一定为0,可更新 } printf("%d\n",ansid); } return 0; }