您的位置:首页 > 其它

zoj 1857 || poj 2607

2011-11-10 01:35 417 查看
又一点多了,昨天好开心,因为小孩子生日。。希望她可以永远快快乐乐的~You are my greatest motivation,really love you.

第一次用spfa,关于spfa具体可看http://hi.baidu.com/qw4365/blog/item/115b211a8ffd14b94aedbcbf.html

/*
zoj_1857    最短路
终于是过了,感觉收获良多~
题意:有n个点,每个点至少一个house,有些点有一个或多个fire station(fs)。求在哪个点增加一个fs,能使
所有house到离它最近的那个fs的最大距离最小。

Process:
1.第一反应就是floyd了,然后犹犹豫豫的写了。
2.居然MLE,改成滚动数组,zoj上TLE了,poj上wa
3.然后发现mark木有初始化(见代码2),改完后zoj上TLE,poj上AC(2000多ms)
4.然后看到网上好像很多人spfa过的,果断学了下spfa,很快写完用spfa实现的代码。
poj上AC,可是居然是4000多ms,zoj肯定TLE啦。。
5.开始查找自己的spfa到底存在什么问题,发现我的spfa里面有句 if( dist[i]>dist[temp]+map[temp][i] )
明显右边是要越界的,速度改成if( map[temp][i]!=inf && dist[i]>dist[temp]+map[temp][i] ),提交后
poj过了(1000多ms),zoj也终于过了,开心~

收获:
1.sscanf的用法
2.spfa
3.改成spfa+邻接表 效率应该是更高的,没有试了。

*/
//代码1:spfa+邻接矩阵(1000多ms)
#include <iostream>
#include <cstdio>
#include <string.h>
#include <limits.h>
#include <queue>
#define inf 99999999
#define N 510
using namespace std;
int flag
;
int ori
,dist
;
int map

;

void inint()
{
int i,j;
for( i=0;i<N;i++ )
{
for( j=0;j<N;j++ )
{
if( i==j ) map[i][j]=0;
else map[i][j]=inf;
}
ori[i]=INT_MAX;
}
memset( flag,0,sizeof(flag) );
}

void spfa( int sta,int n )
{
queue <int>q;
int hash
,temp,i;
memset( hash,0,sizeof(hash) );
for( i=0;i<=n;i++ )
dist[i]=INT_MAX;
dist[sta]=0;
q.push( sta );
hash[sta]=1;
while( !q.empty() )
{
temp=q.front();   q.pop();
hash[temp]=0;
for( i=1;i<=n;i++ )
{
if( map[temp][i]!=inf && dist[i]>dist[temp]+map[temp][i] ) //一开始没写map[temp][i]!=inf,TLE了
{
dist[i]=dist[temp]+map[temp][i];
if( hash[i]==0 )    hash[i]=1 , q.push(i);
}
}
}
}

int findmax( int id,int n )
{
int temp,i,maxi;
maxi=-1;
spfa( id,n );
for( i=1;i<=n;i++ )
if( !flag[i] )
{
temp=ori[i];
if( dist[i]<temp ) temp=dist[i];
if( maxi<temp ) maxi=temp;
}
return maxi;
}

int main()
{
//freopen( "AAA_a.txt","r",stdin );
int n,m,temp,i,j;
int a,b,v,mini,mark;
char str[100];
while( scanf("%d%d",&n,&m)!=EOF )
{
inint();
for( i=0;i<n;i++ )
scanf( "%d",&temp ) , flag[temp]=1 ;
getchar();
while( gets(str) && strlen(str) )
{
sscanf( str,"%d%d%d",&a,&b,&v );
map[a][b]=map[b][a]=v;
}
for( i=1;i<=m;i++ )
if( flag[i] )
{
spfa( i,m );
for( j=1;j<=m;j++ )
if( ori[j]>dist[j] )
ori[j]=dist[j];
}
mini=INT_MAX;
mark=1;
for( i=1;i<=m;i++ )
if( !flag[i] )
{
if( mini>( temp=findmax( i,m ) ) )
mini=temp , mark=i ;
}
printf( "%d\n",mark );
}
return 0;
}


//代码2:floyd+滚动数组(2000多ms)
//poj AC,zoj TLE
#include <iostream>
#include <cstdio>
#include <string.h>
#include <limits.h>
#define inf 99999999
#define N 510
using namespace std;
bool flag
;
int map

;
int dist

[2];
int ori
;

void inint()
{
int i,j;
for( i=0;i<N;i++ )
{
for( j=0;j<N;j++ )
{
if( i==j ) map[i][j]=0;
else map[i][j]=inf;
}
ori[i]=INT_MAX;
}
memset( flag,0,sizeof(flag) );
}

void floyd( int n )
{
int i,j,k;
for( i=0;i<=n;i++ )
for( j=0;j<=n;j++ )
dist[i][j][0]=map[i][j];
for( k=1;k<=n;k++ )
{
for( i=1;i<=n;i++ )
for( j=1;j<=n;j++ )
{
dist[i][j][1]=dist[i][j][0];
if( dist[i][j][1]>dist[i][k][0]+dist[k][j][0] )
dist[i][j][1]=dist[i][k][0]+dist[k][j][0];
}
for( i=1;i<=n;i++ )
for( j=1;j<=n;j++ )
dist[i][j][0]=dist[i][j][1];
}
}

int findmax( int id,int n )
{
int temp,i,maxi;
maxi=-1;
for( i=1;i<=n;i++ )
if( !flag[i] )
{
temp=ori[i];
if( dist[i][id][0]<temp ) temp=dist[i][id][0];
if( maxi<temp ) maxi=temp;
}
return maxi;
}

int main()
{
//freopen( "AAA_a.txt","r",stdin );
int n,m,temp,i,j;
int a,b,v,mini,mark;
char str[100];
while( scanf("%d%d",&n,&m)!=EOF )
{
inint();
for( i=0;i<n;i++ )
scanf( "%d",&temp ) , flag[temp]=1 ;
getchar();
while( gets(str) && strlen(str) )
{
sscanf( str,"%d%d%d",&a,&b,&v );
map[a][b]=map[b][a]=v;
}
floyd(m);
for( i=1;i<=m;i++ )
{
if( !flag[i] )
{
for( j=1;j<=m;j++ )
if( flag[j] && ori[i]>dist[i][j][0] )
ori[i]=dist[i][j][0];
}
else ori[i]=0;
}
mini=INT_MAX;
mark=1;     //这个初始化必须,否则如果每个点都有fire station就错了
for( i=1;i<=m;i++ )
if( !flag[i] )
{
if( mini>( temp=findmax( i,m ) ) || mini==INT_MAX )
mini=temp , mark=i ;
}
printf( "%d\n",mark );
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: