UVA 125 统计路径条数 FLOYD

这道题目折腾了我一个下午,本来我的初步打算是用SPFA(),进行搜索,枚举出发点,看看能到达某个点多少次,就是出发点到该点的路径数,如果出现环,则置为-1,关键在于这个判环过程,如果简单只找到某个点是为环路上一点,即访问它的次数超过了所有点的点数目,这样就会出问题,因为它会影响其他点,下一步是否将它进入队列,如果进入,会造成无限循环,不进的话,根本得不出正确结果,后来我写了个judge函数,判断该点是否还能影响其他点,这样的话,因为要全图搜索,又TLE了。。。

没办法,只好换了网站说的FLOYD;

这是错误的代码:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int u[1000],v[1000],w[1000],nt[1000],ft[50],vis[50],d[50],num[50];
int n,e,maxn,sta[1000],test[1000];
void addedge(int a,int b)
{
    u[e]=a;
    v[e]=b;
    w[e]=0;
    nt[e]=ft[a];
    ft[a]=e++;
}

bool judge(int x)
{
    int j,top=0;
    memset(vis,0,sizeof vis);
    //return dfs(x);
    test[top++]=x;
    vis[x]=1;
    while (top)
    {
        int nx=test[--top];
        if (num[nx]>=0) return 1;
        for (j=ft[nx];j>=0;j=nt[j])
        {
            int ns=v[j];
            if (!vis[ns])
            {
                test[top++]=ns;
                vis[ns]=1;
            }
        }
    }
    return 0;
}
void spfa(int root)
{
    int i,j,top=0;
    memset(vis,0,sizeof vis);
    memset(num,0,sizeof num);
    sta[top++]=root;
    vis[root]=1;
    while (top)
    {
        int x=sta[--top];
        //cout<<x<<" pp "<<endl;
        vis[x]=0;
        for (i=ft[x];i>=0;i=nt[i])
        {
            int nx=v[i];
            //if (nx==x) continue;
            if (num[nx]>=0)
              num[nx]++;
            if (num[nx]>maxn+1)
            {
              num[nx]=-1;
            }
            //cout<<nx<<" nx num "<<num[nx]<<endl;
            //int temp;
            //cin>>temp;
            if (judge(nx))
            {
                sta[top++]=nx;
                vis[nx]=1;
            }
        }
    }
}
int main()
{
    int cnt=0,i,j;
    while (scanf("%d",&n)!=EOF)
    {
        memset(ft,-1,sizeof ft);
        maxn=e=0;
        int a,b;
        for (i=1;i<=n;i++)
        {
            scanf("%d%d",&a,&b);
            addedge(a,b);
            maxn=maxn<a? a:maxn;
            maxn=maxn<b? b:maxn;
        }
        printf("matrix for city %d
",cnt++);
        for (i=0;i<=maxn;i++)
        {
            //cout<<i<<" pp "<<endl;
            spfa(i);
            for (j=0;j<=maxn;j++)
            {
                printf("%d",num[j]);
                if (j<maxn)
                    putchar(' ');
            }
            putchar('
');
        }
    }
    return 0;
}

这是AC的代码

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int g[50][50];
int d[50][50],num[50][50];
int n,maxn;
void init()
{
    for (int i=0; i<50; i++)
    {
        for (int j=0; j<50; j++)
        {
            if (i==j) g[i][j]=0;
            else
                g[i][j]=-1;
            d[i][j]=0;
        }
    }
}
int main()
{
    int i,j,k,cnt=0;
    while (scanf("%d",&n)!=EOF)
    {
        init();
        int a,b;
        maxn=0;
        memset(num,0,sizeof num);
        for (i=1; i<=n; i++)
        {
            scanf("%d%d",&a,&b);
            g[a][b]=1;
            num[a][b]=1;
            maxn=maxn>a ? maxn:a;
            maxn=maxn>b ? maxn:b;
        }
        for (i=0; i<=maxn; i++)
        {
            for (j=0; j<=maxn; j++)
            {
                for (k=0; k<=maxn; k++)
                {
                    //if (j==k) continue;
                    if (num[j][i] && num[i][k])
                    num[j][k]+=num[j][i]*num[i][k];
                }
            }
        }
        for (i=0;i<=maxn;i++)
        {
            if (num[i][i]>0)
            {
                for (j=0;j<=maxn;j++)
                {
                    for (k=0;k<=maxn;k++)
                    {
                        if (num[j][i] && num[i][k])
                            num[j][k]=-1;
                    }
                }
            }
        }
        printf("matrix for city %d
",cnt++);
        for (i=0;i<=maxn;i++)
        {
            for (j=0;j<=maxn;j++)
            {
                printf("%d",num[i][j]);
                if (j<maxn) putchar(' ');
            }
            putchar('
');
        }
    }
    return 0;
}

FLOYD用这道题目原理很简单,就是因为它能算出所有点点的距离,因此用它来计算点点之间的路径数也是理所应当的可以。。关键在于成环的判断,一旦有某点num[k][k]>0,则该点必定在环内。。因此进行置-1操作。最后打印结果即可。

原文地址:https://www.cnblogs.com/kkrisen/p/3519586.html