第四题
P2683 小岛
考点:Floyd算法的变形
以下自己的代码,这个题通过了,但是耗时太久(5.4s)
代码一
/*----4-------*/
const int INF=10000000;
const int maxn=110;
int n,m,dis[maxn][maxn];
bool flag=false;
void Floy(){
for(int k=1;k<=n;k++){
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
if(dis[i][k]!=INF&&dis[k][k]!=INF&&dis[i][k]+dis[k][j]<dis[i][j])
dis[j][i]=dis[i][j]=dis[i][k]+dis[k][j];
}
}
}
flag=false;
}
int main(){
// freopen("in.txt","r",stdin);
scanf("%d%d",&n,&m);
fill(dis[0],dis[0]+maxn*maxn,INF);
for(int i=1;i<=n;i++){
dis[i][i]=0;
}
int num,u,v,wt;
while(m--){
scanf("%d",&num);
if(num==1){
scanf("%d%d%d",&u,&v,&wt);
if(dis[u][v]>wt){
dis[u][v]=dis[v][u]=wt;
flag=true;
}
}else if(num==0){
if(flag) Floy();
scanf("%d%d",&u,&v);
if(dis[u][v]!=INF) printf("%d\n",dis[u][v]);
else printf("-1\n");
}
}
}
代码二
其中j必须从1-n,因为此时岛1->岛2与岛2->岛1经过的道路并不同
例如:dis[2[3]变小
此时dis[1][2]与dis[1][2]+dis[2][3]+dis[3][2],即路线1->2->3->2
此时dis[2][1]与dis[2][2]+dis[2][3]+dis[3][1]也即2->2->3->1
即2->3->1由此可知改变边时,以1为起点,2为终点和以2为起点,1为终点,计算的结果并不一样
这和原始floyd三层for循环的算法改变一个点(k)不一样,1->3->2与2->3->1路径是一样的,所以可以j从i+1开始遍历
//代码用时:398ms
#include"cstdio"
#include"algorithm"
#include"cstring"
using namespace std;
const int maxn=105;
const int inf=10000000;
int n,m,dis[maxn][maxn];
void floyd(int x,int y){
for(int i=1;i<=n;i++){
// for(int j=i+1;j<=n;j++){
//这样写是错误的
for(int j=1;j<=n;j++){
if(dis[i][x]+dis[x][y]+dis[y][j]<dis[i][j]){
dis[i][j]=dis