早期代码 、代码很烂
http://acm.hdu.edu.cn/showproblem.php?pid=2544 //基础
http://acm.hdu.edu.cn/showproblem.php?pid=1874 //基础+
http://acm.hdu.edu.cn/showproblem.php?pid=2066 //聚点
Problem - 2544 (hdu.edu.cn)
很基础的最短路径算法的题目, 注意数据的范围,做好初始化;
AC 代码:
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int n,m;
const int maxn=110;
const int inf=1e9;
int d[maxn];
int t[maxn][maxn];
bool v[maxn];
void cc()
{
for(int i=0;i<=n;i++)
for(int j=0;j<=n;j++)
if(i!=j) t[i][j]=inf;
memset(v,0,sizeof(v));
v[n]=0;
for(int i=1;i<=n;i++) d[i]=inf;
d[n+1]=inf;
}
void dis()
{
int x=1;v[x]=1;d[x]=0;
for(int k=0;k<n;k++)
{
for(int i=1;i<=n;i++)
{
if(!v[i]&&t[x][i]!=inf)
d[i]=min(d[i],t[x][i]+d[x]);
}
int tx=n+1;
for(int i=1;i<=n;i++)
if(!v[i])
tx=d[tx]<d[i]?tx:i;
x=tx;
v[tx]=1;
}
}
int main()
{
while(cin>>n>>m&&m!=0&&n!=0)
{
cc();
int x,y,z;
for(int i=0;i<m;i++)
{
cin>>x>>y>>z;
t[x][y]=t[y][x]=z;
}
dis();
cout<<d[n]<<endl;
}
}
Problem - 1874 (hdu.edu.cn)
和上一个题难度一样,只是改了一下起点和终点的位置,至于需不需要剪支,没有测试过 ,根据数据范围来看,应该不会超限的;
不知道是不是判断平台的问题 ,没有该scanf之前 可能一直处于超限状态,最后是改t的赋值之后才对的,因为题目没说两地之间会不会有重复的道路
AC代码:
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=210;
const int inf=1e9+1;
int d[maxn];
int t[maxn][maxn];
bool v[maxn];
int n,m,S,T;
void cc()
{
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
if(i!=j) t[i][j]=inf;
for(int i=0;i<n;i++) v[i]=0;
for(int i=0;i<=n;i++) d[i]=inf;
}
void dis()
{
int x=S;v[S]=1;d[S]=0;
for(int k=0;k<n;k++)
{
for(int i=0;i<n;i++)
if(!v[i]&&t[x][i]!=inf)
d[i]=min(d[i],t[x][i]+d[x]);
int tx=n;
for(int i=0;i<n;i++)
if(!v[i])
tx=d[tx]<d[i]?tx:i;
if(tx==T) break;
x=tx;
v[x]=1;
}
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
cc();
int x,z,y;
for(int i=0;i<m;i++)
{
scanf("%d%d%d",&x,&y,&z);
t[x][y]=t[y][x]=min(t[x][y],z);
}
scanf("%d%d",&S,&T);
dis();
if(d[T]==inf)
printf("-1\n");
else
printf("%d\n",d[T]);
}
}
Problem - 2066 (hdu.edu.cn)
很有意思的一个题目;
1.最开始想法是一次迪捷斯算法 然后从想去的地方找出最小的。喜提WA
2.之后改scanf ,
3.后面竟然还优化了一下代码的写法
if(!v[i]&&t[x][i]!=inf) d[i]=min(d[i],t[x][i]+d[x]);
直接删成 if(!v[i]) d[i]=min(d[i],t[x][i]+d[x]);
这总估计也算不上优化吧 在写法上能偷懒,但是如果数据爆的话这总写法是不可以的
4.
散->聚
聚集起点的方法不难想出来,就是设起点为0,起点到联通点的距离为0,这也是算法要实现必须要做的。
那么聚集终点捏?
也是可以的 方法同聚集起点,这样聚集终点的好处,能提前结束算法,不用迭代出0到i所有点的距离再比较要去点的大小。这种优化是非常可观的。
AC代码
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=1e3+10;
const int inf=1e6;
int t[maxn][maxn];
int d[maxn];
bool v[maxn];
int tcity[maxn];
int m,n,D;
int maxcity;
void cc1()
{
for(int i=0;i<maxn;i++)
for(int j=0;j<maxn;j++)
if(i!=j) t[i][j]=inf;
memset(v,0,sizeof(v));
for(int i=0;i<maxn;i++) d[i]=inf;
maxcity=0;
}
void dis()
{
int x=0;v[x]=1;d[x]=0;
for(int k=0;k<maxcity;k++)
{
for(int i=1;i<=maxcity;i++)
{
if(!v[i]) d[i]=min(d[i],t[x][i]+d[x]);
}
int tx=maxcity+1;
for(int i=1;i<=maxcity;i++)
if(!v[i])
tx=d[tx]<d[i]?tx:i;
x=tx;
v[x]=1;
if(x==maxcity) break;
}
}
int main()
{
while(~scanf("%d%d%d",&m,&n,&D))
{
cc1();
int x,y,z;
for(int i=0;i<m;i++)
{
scanf("%d%d%d",&x,&y,&z);
t[x][y]=t[y][x]=min(t[x][y],z);
maxcity=max(x,max(maxcity,y));
}
maxcity++;
for(int i=0;i<n;i++)
{
scanf("%d",&x);
t[x][0]=t[0][x]=0;
}
for(int i=0;i<D;i++)
{
scanf("%d",&x);
t[x][maxcity]=t[maxcity][x]=0;//聚集
}
dis();
printf("%d\n",d[maxcity]);
}
}