2010-1066

从 Trac 迁移的文章

这是从旧校内 Wiki 迁移的文章,可能存在一些样式问题,您可以向 memset0 反馈。

原文章内容如下:

Contest 1 Conference Call

结题报告。

  题目描述是说有一个电话网,每一个电话连在网中的一个节点上,一个节点可以连多个电话。网构成了一个无向图。题目数据给出了三个需要互相连通的电话,问怎样架设网络使他们连通。

  三个点连通显然有一个中心点,但是如果枚举中心点,那么时间复杂度为500(中心)*(500*500)(dijkstra)超时。考虑到求最短路只有对三个需求点的数据才有效,所以可以先以需求的三个点为源求出最短路,然后枚举中心点,复杂度为O(n!^ 2)。

  程序如下:三次最短路没有在一起写,直接复制粘贴了改改参数。

{{{
#!cpp
#include <cstdio>
#include <cstring>
int phone[10001];
int dis[501][501];
int disa[501];
int disb[501];
int disc[501];
int a,b,c;
int n,m,l;
void dija()
{
    int used[501]  ;
    memset(used,0,sizeof(used));
    for (int i=1;i<=m;i++)
        disa[i]=0xffffff;
    disa[a]=0;
    for (int i=1;i<=m;i++)
    {
        int min=0xffffff;
        int minindex=0;
        for (int i=1;i<=m;i++)
            if (used[i]&&disa[i]<min)
            {
                min=disa[i];
                minindex=i;
            }
        if(min==0xffffff)
            return;
        used[minindex]=true;
        for (int i=1;i<=m;i++)
            if (disa[minindex]+dis[minindex][i]<disa[i])
                disa[i]=disa[minindex]+dis[minindex][i];
    }
}
void dijb()
{
    int used[501]  ;
    memset(used,0,sizeof(used));
    for (int i=1;i<=m;i++)
        disb[i]=0xffffff;
    disb[b]=0;
    for (int i=1;i<=m;i++)
    {
        int min=0xffffff;
        int minindex=0;
        for (int i=1;i<=m;i++)
            if (used[i]&&disb[i]<min)
            {
                min=disb[i];
                minindex=i;
            }
        if(min==0xffffff)
            return;
        used[minindex]=true;
        for (int i=1;i<=m;i++)
            if (disb[minindex]+dis[minindex][i]<disb[i])
                disb[i]=disb[minindex]+dis[minindex][i];
    }
}
void dijc()
{
    int used[501]  ;
    memset(used,0,sizeof(used));
    for (int i=1;i<=m;i++)
        disc[i]=0xffffff;
    disc[c]=0;
    for (int i=1;i<=m;i++)
    {
        int min=0xffffff;
        int minindex=0;
        for (int i=1;i<=m;i++)
            if (used[i]&&disc[i]<min)
            {
                min=disc[i];
                minindex=i;
            }
        if(min==0xffffff)
            return;
        used[minindex]=true;
        for (int i=1;i<=m;i++)
            if (disc[minindex]+dis[minindex][i]<disc[i])
                disc[i]=disc[minindex]+dis[minindex][i];
    }
}
int main()
{
    int cases=0;
    while (scanf("%d %d %d",&n,&m,&l)!=EOF)
    {
        cases++;
        for (int i=1;i<=m;i++)
            for (int j=1;j<=m;j++)
                dis[i][j]=0xffffff;
        for (int i=1;i<=n;i++)
            scanf("%d",&phone[i]);
        for (int i=1;i<=l;i++)
        {
            scanf("%d%d%d",&a,&b,&c);
            dis[a][b]=c;
            dis[b][a]=c;
        }
        int p;
        scanf("%d",&p);
        printf("Case #%d\n",cases);
        for (int s=1;s<=p;s++)
        {
            scanf("%d%d%d",&a,&b,&c);
            a=phone[a];
            b=phone[b];
            c=phone[c];
            dija();         //求a为源最短路
            dijb();         //求b为源最短路
            dijc();         //求c为源最短路
            int min=0xffffff;
            for (int i=1;i<=m;i++)//枚举中心点
            {
                if (disa[i]+disb[i]+disc[i]<min)
                    min=disa[i]+disb[i]+disc[i];
            }
            if (min!=0xffffff)
                printf("Line %d: The minimum cost for this line is %d.\n",s,min);
            else
                printf("Line %d: Impossible to connect!\n",s);
        }
    }
}
}}}

Contest 1 Conference Call

结题报告。

题目描述是说有一个电话网,每一个电话连在网中的一个节点上,一个节点可以连多个电话。网构成了一个无向图。题目数据给出了三个需要互相连通的电话,问怎样架设网络使他们连通。

三个点连通显然有一个中心点,但是如果枚举中心点,那么时间复杂度为500(中心)*(500*500)(dijkstra)超时。考虑到求最短路只有对三个需求点的数据才有效,所以可以先以需求的三个点为源求出最短路,然后枚举中心点,复杂度为O(n!^ 2)。

程序如下:三次最短路没有在一起写,直接复制粘贴了改改参数。

#include <cstdio>
#include <cstring>
int phone[10001];
int dis[501][501];
int disa[501];
int disb[501];
int disc[501];
int a,b,c;
int n,m,l;
void dija()
{
    int used[501]  ;
    memset(used,0,sizeof(used));
    for (int i=1;i<=m;i++)
        disa[i]=0xffffff;
    disa[a]=0;
    for (int i=1;i<=m;i++)
    {
        int min=0xffffff;
        int minindex=0;
        for (int i=1;i<=m;i++)
            if (used[i]&&disa[i]<min)
            {
                min=disa[i];
                minindex=i;
            }
        if(min==0xffffff)
            return;
        used[minindex]=true;
        for (int i=1;i<=m;i++)
            if (disa[minindex]+dis[minindex][i]<disa[i])
                disa[i]=disa[minindex]+dis[minindex][i];
    }
}
void dijb()
{
    int used[501]  ;
    memset(used,0,sizeof(used));
    for (int i=1;i<=m;i++)
        disb[i]=0xffffff;
    disb[b]=0;
    for (int i=1;i<=m;i++)
    {
        int min=0xffffff;
        int minindex=0;
        for (int i=1;i<=m;i++)
            if (used[i]&&disb[i]<min)
            {
                min=disb[i];
                minindex=i;
            }
        if(min==0xffffff)
            return;
        used[minindex]=true;
        for (int i=1;i<=m;i++)
            if (disb[minindex]+dis[minindex][i]<disb[i])
                disb[i]=disb[minindex]+dis[minindex][i];
    }
}
void dijc()
{
    int used[501]  ;
    memset(used,0,sizeof(used));
    for (int i=1;i<=m;i++)
        disc[i]=0xffffff;
    disc[c]=0;
    for (int i=1;i<=m;i++)
    {
        int min=0xffffff;
        int minindex=0;
        for (int i=1;i<=m;i++)
            if (used[i]&&disc[i]<min)
            {
                min=disc[i];
                minindex=i;
            }
        if(min==0xffffff)
            return;
        used[minindex]=true;
        for (int i=1;i<=m;i++)
            if (disc[minindex]+dis[minindex][i]<disc[i])
                disc[i]=disc[minindex]+dis[minindex][i];
    }
}
int main()
{
    int cases=0;
    while (scanf("%d %d %d",&n,&m,&l)!=EOF)
    {
        cases++;
        for (int i=1;i<=m;i++)
            for (int j=1;j<=m;j++)
                dis[i][j]=0xffffff;
        for (int i=1;i<=n;i++)
            scanf("%d",&phone[i]);
        for (int i=1;i<=l;i++)
        {
            scanf("%d%d%d",&a,&b,&c);
            dis[a][b]=c;
            dis[b][a]=c;
        }
        int p;
        scanf("%d",&p);
        printf("Case #%d\n",cases);
        for (int s=1;s<=p;s++)
        {
            scanf("%d%d%d",&a,&b,&c);
            a=phone[a];
            b=phone[b];
            c=phone[c];
            dija();         //求a为源最短路
            dijb();         //求b为源最短路
            dijc();         //求c为源最短路
            int min=0xffffff;
            for (int i=1;i<=m;i++)//枚举中心点
            {
                if (disa[i]+disb[i]+disc[i]<min)
                    min=disa[i]+disb[i]+disc[i];
            }
            if (min!=0xffffff)
                printf("Line %d: The minimum cost for this line is %d.\n",s,min);
            else
                printf("Line %d: Impossible to connect!\n",s);
        }
    }
}