记录刷到的然后不咋会的/值得记录的图论题
poj2253
frogger
这个题我觉得挺奇妙的)),大概是我遇到的第一个图论变形题。
基本题意:
有一堆点(编号从1到n),起点和终点分别在1,2上。每个点之间都联通,给出了点的坐标(易得每个点之间的距离)。问怎么走,才能让走过每两个点的距离最小。就是对于任意通路,如何使的每单条路的最大长度最小,这个最小长度就是ans。
举个栗子
如图,
起点为1,终点为2
那么对于这个图,ans=2。
从起点到终点可以选择从1->2或者1->3->2,第二条路的单条路的最大值为2,比第一条小。
思路:运用Dijkstra算法,对路径进行松弛,dis数组存下起点到该点的最大单条路长度。
const int maxnum=307;
const int inf=0x3f3f3f3f;
int x[maxnum],y[maxnum],n;
double mp[maxnum][maxnum];
double dis[maxnum];
int vis[maxnum];
void dj()
{
memset(vis,0,sizeof vis);
for(int i=1; i<=n; i++)
dis[i]=inf;
dis[1]=0;
for(int i=1; i<=n; i++)//合并n个点
{
int minn=inf,k;
for(int j=1; j<=n; j++)
if(vis[j]==0&&dis[j]<minn)
{
k=j;
minn=dis[j];
}
vis[k]=1;
for(int j=1; j<=n; j++)
dis[j]=min(dis[j],max(dis[k],mp[k][j]));//dis[j]为从一号石头到第j号石头所有通路中最长边中的最小边
}
}
int main()
{
int q=1;
while(~scanf("%d",&n)&&n)
{
memset(mp,0,sizeof mp);
for(int i=1; i<=n; i++)
scanf("%d%d",&x[i],&y[i]);
for(int i=1; i<=n; i++)
for(int j=i+1; j<=n; j++)
mp[i][j]=mp[j][i]=sqrt(double(x[i]-x[j])*(x[i]-x[j])+double(y[i]-y[j])*(y[i]-y[j]));
dj();
printf("Scenario #%d\nFrog Distance = %.3lf\n\n",q++,dis[2]);
}
return 0;
}