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
#include

using 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;
}

但是我一开始想到的不是这个做法,而是最小生成树
结果证明这也是对的
唯一需要注意的就是图不一定联通,所以每个连通块都要dfs一遍
这样的复杂度应该是O(n^2),比floyed好,但是代码较长,需要注意细节

//这里写代码片
#include
#include
#include
#include

using 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/LA,图论)