由poj 1125,poj 1062解析最短路径
一、poj 1125(有向图,未定义起始点和终点)
题意:给出一个图,点表示人,边表示消息从这个人传到另一个人所花的时间,你的任务是求把消息告诉里面的哪一个人(假设你只能告诉一个人),能让消息遍布整个网络所花的最少时间,并求最少时间。
//这个题目题意比题解难。。。。
题解:首先从n个人中选择一个人,把消息告诉他,然后用一个求单源最短路径算法求出其他所有人收到消息的最短时间,然后最大的最短时间就是消息遍布整个网络所花的最少时间。然后再在n个最少时间中选出最少的,即是答案。
#include<stdio.h>
#define inf 10000
int dij();
int n,i,k,t,d[101],e[101][101],max1,max2,used[101],m;
int main(){
while(~scanf("%d",&n),n)
{ for(i=0;i<n;i++)
for(k=0;k<n;k++)
{e[i][k]=inf;d[i]=inf;}
max1=10000,max2=0,m=1111;
for(i=0;i<n;i++)
{
scanf("%d",&k);
while(k--)
{ scanf("%d",&t);
scanf("%d",&e[i][t-1]);
}
}
{for(k=0;k<n;k++) printf("%d ",e[i][k]); printf("\n"); }*/
for(i=0;i<n;i++)
{
max2=dij(i);
if(max2<max1) {max1=max2;m=i+1;}
}
printf("%d %d\n",m,max1);
}
}
int dij(int s){ int v,u,max=0;
memset(used,0,sizeof(used));
for(u=0;u<n;u++)
d[u]=inf;
d[s]=0;
while(1)
{ v=-1;
for(u=0;u<n;u++)
{ if(!used[u]&&(v==-1||d[u]<d[v]))
v=u;
}
if(v==-1) break;
used[v]=1;
for(u=0;u<n;u++)
if(d[u]>d[v]+e[v][u])
d[u]=d[v]+e[v][u];
if(v!=s&&d[v]>max) max=d[v];
}// printf("%d**\n",max);
return max;
}
二、poj1062(有向图,定义了起始点和终点,但对路径有要求)
难得的中文题,题目见http://poj.org/problem?id=1062
模拟出图,可设村夫所在起始点为0点,如直接到1点(酋长的许诺),需要花费10000,即0,1两点边权为10000.
此题难点在于对路径的要求
方法一:对路径进行枚举
假设某一点为最高权限点,把权限比他高的点以及与它权限差超过限制条件的点舍弃,再对剩余点求最短路径。
方法二:递归求最短路(需要是有向图)
#include<stdio.h>
#define inf 1<<30
int M,N,i,k,d[101][101],a[101],vis[101],MIN=inf,t,ds[101];void dfs();
int main(){ memset(a,0,sizeof(a));
memset(vis,0,sizeof(vis));
scanf("%d%d",&M,&N);
for(i=0;i<=N;i++)
for(k=0;k<=N;k++)
{d[i][k]=inf;ds[i]=inf;}
for(i=1;i<=N;i++)
{ scanf("%d%d%d",&d[0][i],&a[i],&k);
ds[i]=d[0][i];
while(k--)
{
scanf("%d",&t);
scanf("%d",&d[t][i]);
}
}
dfs(1,a[1],a[1]);
printf("%d\n",ds[1]);
return 0;}
void dfs(int v ,int maxl , int minl){ int u;
int max,min;
if(vis[v]) return ;
vis[v]=1;
for(u=1; u<=N; u++) if(d[u][v]!=inf) //有边
{
max=maxl>a[u]?maxl:a[u];
min=minl<a[u]?minl:a[u];
if(max-min<=M) //在路径中任意点的等级差不能超过M
{
dfs(u,max,min);
if(d[u][v]+ds[u]<ds[v])
ds[v]=d[u][v]+ds[u];
}
}
return;}
//此题搜索可做,但超时也是肯定的