由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;}
//此題搜索可做,但超時也是肯定的