uva 10048 Audiophobia
DP(仿照Floyd)
题意:一个无向图,然后多个查询,查询是起点和终点s和t,s到t可能有多条路径,那么每条路径都会有一条权值最大的边,在所有的最大边中找一个最小的,如果s到t之间不连通,那么输出no path
想了很久,大概有两个小时的样子…………然后看了一下数据,刚好最多有100个点,最多10000个查询,那么就给了一个很大的启发,会不会有一个算法会好像dij一样,运行一次能得到做个答案,或者一个算法好像floyd一样,运行一次可以知道所有答案,出于数据的特殊性,我更倾向于往floyd的方向想。
floyd的本质是DP,其实这个问题也很容易发现就是个DP,状态转移方程为
max=MAX{ d[i][k] , d[k][j]}
d[i][j]=MIN{d[i][j] , max}
DP思想很容易想到,从i到j,如果经过k点,并且i到k是连通的,k到j是连通的,那么d[i][k]表示i到k的最大值的最小值,d[k][j]表示k到j的最大值的最小值
那么合并两条路径后,最大值的最小值应该是两者中的较大的那个
然后从i到j本身有已有一个最大值的最小值,再比较两者哪个更小,取较小值
当d[i][j]=INF,表示i到j不连通,那么就谈不上什么最大值的最小值
其中初始化d[i][j]=g[i][j]
#include <cstdio>
#include <cstring>
#define INF 0x3f3f3f3f
#define N 110
int d[N][N];
int n,m,mm;
int max(int a ,int b)
{ return a>b?a:b; }
int min(int a, int b)
{ return a<b?a:b; }
void DP()
{
for(int k=1; k<=n; k++)
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
d[i][j]=min(d[i][j],max(d[i][k],d[k][j]));
return ;
}
int main()
{
int T=0;
while(scanf("%d%d%d",&n,&m,&mm)!=EOF)
{
if(!n && !m && !mm) break;
memset(d,0x3f,sizeof(d));
for(int i=1; i<=m; i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
d[u][v]=d[v][u]=w;
}
DP();
T++;
if(T!=1) printf("\n");
printf("Case #%d\n",T);
for(int i=1; i<=mm; i++)
{
int u,v;
scanf("%d%d",&u,&v);
if(d[u][v]==INF) printf("no path\n");
else printf("%d\n",d[u][v]);
}
}
return 0;
}
DP里面的拓展开来可以这样写(方便理解)
if(d[i][k]==INF || d[k][j]==INF) continue; int m; if(d[i][k]>d[k][j]) m=d[i][k]; else m=d[k][j]; if(m<d[i][j]) d[i][j]=m;

浙公网安备 33010602011771号