UVa/LA|UVa10048 - Audiophobia(floyed|最小生成树)
题目链接
简介:
要求两点之间最大路径权值最小,输出这个最大路径
分析:
书上给了一种很简单的做法:floyed
G[i][j]=min(G[i][j],max(G[i][k],G[k][j]));
这样做为什么对呢?
因为无论是floyed和dijkstra,都是基于这样一个事实:
对于任何一条至少包含两条边的路径i—>j,一定存在一个k,使得i—>j的总长度等于i—>k和k—>j的路径和
对于不同的点k,i—>k和k—>j的长度之和可能不同,但是最后还需要取一个min
//这里写代码片
#include
#include
#includeusing namespace std;
const int INF=0x33333333;
int f[103][103];
int G[103][103];
int n,m,Q;
void floyed()
{
int i,j,k;
for (k=1;
k<=n;
k++)
for (i=1;
i<=n;
i++)
if (i!=k)
for (j=1;
j<=n;
j++)
{
G[i][j]=min(G[i][j],max(G[i][k],G[k][j]));
}
}int main()
{
int cnt=0;
while (scanf("%d%d%d",&n,&m,&Q)!=EOF&&n)
{
if (cnt++) printf("\n");
printf("Case #%d\n",cnt);
memset(G,0x33,sizeof(G));
for (int i=1;
i<=m;
i++)
{
int u,w,z;
scanf("%d%d%d",&u,&w,&z);
G[u][w]=G[w][u]=z;
}
floyed();
for (int i=1;
i<=Q;
i++)
{
int u,w;
scanf("%d%d",&u,&w);
if (G[u][w]==INF) printf("no path\n");
else printf("%d\n",G[u][w]);
}
}
return 0;
}
【UVa/LA|UVa10048 - Audiophobia(floyed|最小生成树)】但是我一开始想到的不是这个做法,而是最小生成树
结果证明这也是对的
唯一需要注意的就是图不一定联通,所以每个连通块都要dfs一遍
这样的复杂度应该是O(n^2),比floyed好,但是代码较长,需要注意细节
//这里写代码片
#include
#include
#include
#includeusing namespace std;
const int INF=0x33333333;
int f[103][103];
struct node{
int x,y,v,nxt;
bool operator < (const node &a) const
{
return v210],e[1003];
int n,m,Q,st[103],tot,fa[103];
int p[103];
void unionn(int f1,int f2){fa[f1]=f2;
}
int find(int x)
{
if (fa[x]!=x) fa[x]=find(fa[x]);
return fa[x];
}void add(int u,int w,int v)
{
tot++;
way[tot].x=u;
way[tot].y=w;
way[tot].v=v;
way[tot].nxt=st[u];
st[u]=tot;
tot++;
way[tot].x=w;
way[tot].y=u;
way[tot].v=v;
way[tot].nxt=st[w];
st[w]=tot;
}void Kruskal()
{
sort(e+1,e+1+m);
for (int i=1;
i<=n;
i++) fa[i]=i;
for (int i=1;
i<=m;
i++)
{
int f1=find(e[i].x);
int f2=find(e[i].y);
if (f1!=f2)
{
unionn(f1,f2);
add(e[i].x,e[i].y,e[i].v);
}
}
}void dfs(int now,int ff,int z,int bz)
{
for (int i=1;
i<=n;
i++)
if (p[i]==bz)
{
f[i][now]=max(f[i][ff],z);
f[now][i]=f[i][now];
}
p[now]=bz;
//在这里改标记
for (int i=st[now];
i;
i=way[i].nxt)
if (way[i].y!=ff)
{
f[now][way[i].y]=f[way[i].y][now]=way[i].v;
//
dfs(way[i].y,now,way[i].v,bz);
}
}int main()
{
int cnt=0;
while (scanf("%d%d%d",&n,&m,&Q)!=EOF&&n)
{
if (cnt++) printf("\n");
printf("Case #%d\n",cnt);
memset(st,0,sizeof(st));
tot=0;
for (int i=1;
i<=m;
i++)
scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].v);
Kruskal();
memset(p,0,sizeof(p));
memset(f,128,sizeof(f));
for (int i=1;
i<=n;
i++)
if (p[i]==0) dfs(i,0,0,i);
for (int i=1;
i<=Q;
i++)
{
int u,w;
scanf("%d%d",&u,&w);
if (f[u][w]<0) printf("no path\n");
else printf("%d\n",f[u][w]);
}
}
return 0;
}
推荐阅读
- UVA 10763
- 729uva海明距离问题
- 搜索技术|UVA10054 The Necklace——欧拉回路(DFS)
- 四分树( Quadtrees, UVa 297)
- UVA 108 Maximum Sum (最大子矩阵和) POJ 1050
- UVa, 11000 Bee
- UVA|uva 589 - Pushing Boxes(双重bfs)
- UVA 589 - Pushing Boxes(BFS+状态判重)
- 趣学英语(防晒霜上的spf和uva是什么意思())
- 解题报告|UVa 10783 - Odd Sum