http://wikioi.com/problem/1041/
建图是关键机场通过铁路,城市有4个机场可以到达,可以出发
(告诉3个点有多个情况:1,2为对角,1,3为对角,2,3为对角)
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
double map[110][5][110][5];//i的k1到j的k2
int n;
int s,t,a,b;
int x[5],y[5];
struct node
{
int x[5],y[5];
}zb[110];
int vis[100+10][5];
double d[100+10][5];
const int inf=0x3f3f3f3f;
void tu()//相练习耐心就写吧
{
for(int i=1;i<=s;i++)
{
int st;
scanf("%d%d%d%d%d%d%d",&x[1],&y[1],&x[2],&y[2],&x[3],&y[3],&st);
double l1,l2,l3;
l1=sqrt((x[1]-x[2])*(x[1]-x[2])+(y[1]-y[2])*(y[1]-y[2]));
map[i][2][i][1]=map[i][1][i][2]=l1*st;
l2=sqrt((x[1]-x[3])*(x[1]-x[3])+(y[1]-y[3])*(y[1]-y[3]));
map[i][3][i][1]=map[i][1][i][3]=l2*st;
l3=sqrt((x[3]-x[2])*(x[3]-x[2])+(y[3]-y[2])*(y[3]-y[2]));
map[i][3][i][2]=map[i][2][i][3]=l3*st;
if((x[1]-x[2])*(x[1]-x[2])+(y[1]-y[2])*(y[1]-y[2])+(x[1]-x[3])*(x[1]-x[3])+(y[1]-y[3])*(y[1]-y[3])==(x[3]-x[2])*(x[3]-x[2])+(y[3]-y[2])*(y[3]-y[2]))
{
x[4]=x[3]+x[2]-x[1];
y[4]=y[3]+y[2]-y[1];
}
else if((x[1]-x[2])*(x[1]-x[2])+(y[1]-y[2])*(y[1]-y[2])+(x[3]-x[2])*(x[3]-x[2])+(y[3]-y[2])*(y[3]-y[2])==(x[1]-x[3])*(x[1]-x[3])+(y[1]-y[3])*(y[1]-y[3]))
{
x[4]=x[3]+x[1]-x[2];
y[4]=y[3]+y[1]-y[2];
}
else if((x[3]-x[2])*(x[3]-x[2])+(y[3]-y[2])*(y[3]-y[2])+(x[1]-x[3])*(x[1]-x[3])+(y[1]-y[3])*(y[1]-y[3])==(x[1]-x[2])*(x[1]-x[2])+(y[1]-y[2])*(y[1]-y[2]))
{
x[4]=x[1]+x[2]-x[3];
y[4]=y[1]+y[2]-y[3];
}
for(int j=1;j<=3;j++)
{
map[i][4][i][j]=map[i][j][i][4]=sqrt((x[4]-x[j])*(x[4]-x[j])+(y[4]-y[j])*(y[4]-y[j]))*st;
}
for(int k=1;k<=4;k++)
{
zb[i].x[k]=x[k];
zb[i].y[k]=y[k];
}//城市保存个结构
}
for(int i=1;i<=s;i++)
{
for(int j=i+1;j<=s;j++)
{
for(int k1=1;k1<=4;k1++)
for(int k2=1;k2<=4;k2++)
{
double l5=sqrt((zb[i].x[k1]-zb[j].x[k2])*(zb[i].x[k1]-zb[j].x[k2])+(zb[i].y[k1]-zb[j].y[k2])*(zb[i].y[k1]-zb[j].y[k2]));
map[i][k1][j][k2]=map[j][k2][i][k1]=l5*t;
//printf("l5==%.3lf map[%d][%d][%d][%d]==%.3lf\n",l5,i,k1,j,k2,map[i][k1][j][k2]);
}
}
}
}
void dij()
{
double ans=inf;
for(int l=1;l<=4;l++)//出发位置
{
memset(vis,0,sizeof(vis));
for(int i=1;i<=s;i++)
for(int j=1;j<=4;j++)d[i][j]=999999.9;
d[a][l]=0;
for(int i=1;i<=4*s;i++)
{
int x,y;
double m=inf;
for(int j=1;j<=s;j++)
{
for(int k1=1;k1<=4;k1++)if(!vis[j][k1]&&d[j][k1]<=m)
{
m=d[j][k1];
x=j;
y=k1;
}
}
vis[x][y]=1;
for(int j=1;j<=s;j++)
{
for(int k1=1;k1<=4;k1++)//注意是4个机场
{
d[j][k1]=min(d[j][k1],d[x][y]+map[x][y][j][k1]);
}
}
for(int j=1;j<=4;j++)ans=min(ans,d[b][j]);
}
}
printf("%.1lf\n",ans);
}
int main()
{
scanf("%d",&n);
for(int ji=1;ji<=n;ji++)
{
memset(map,0,sizeof(map));
scanf("%d%d%d%d",&s,&t,&a,&b);
tu();
dij();
}
return 0;
}