• 洛谷 P1078 文化之旅 解题报告


    P1078 文化之旅

    题目描述

    有一位使者要游历各国,他每到一个国家,都能学到一种文化,但他不愿意学习任何一种文化超过一次(即如果他学习了某种文化,则他就不能到达其他有这种文化的国家)。不同的国家可能有相同的文化。不同文化的国家对其他文化的看法不同,有些文化会排斥外来文化(即如果他学习了某种文化,则他不能到达排斥这种文化的其他国家)。

    现给定各个国家间的地理关系,各个国家的文化,每种文化对其他文化的看法,以及这位使者游历的起点和终点(在起点和终点也会学习当地的文化),国家间的道路距离,试求从起点到终点最少需走多少路。

    输入输出格式

    输入格式:

    第一行为五个整数 (N,K,M,S,T),每两个整数之间用一个空格隔开,依次代表国家个数(国家编号为1到(N)),文化种数(文化编号为1到(K)),道路的条数,以及起点和终点的编号(保证(S)不等于(T));

    第二行为(N)个整数,每两个整数之间用一个空格隔开,其中第(i)个数(C_i),表示国家(i)的文化为(C_i)

    接下来的(K)行,每行(K)个整数,每两个整数之间用一个空格隔开,记第(i)行的第(j)个数为(a_{ij}),(a_{ij}=1)表示文化(i)排斥外来文化(j)(i) 等于(j)时表示排斥相同文化的外来人),(a_{ij}=0)表示不排斥(注意(i)排斥(j)并不保证(j)一定也排斥(i))。

    接下来的(M)行,每行三个整数(u,v,d) ,每两个整数之间用一个空格隔开,表示国家(u)与国家(v)有一条距离为(d)的可双向通行的道路(保证(u)不等于(v) ,两个国家之间可能有多条道路)。

    输出格式:

    一个整数,表示使者从起点国家到达终点国家最少需要走的距离数(如果无解则输出 −1 )。


    UPT:这是个错题,无视吧。

    这道题教会了我一个道理,当数据比较小时,只要复杂度正确,怎么暴力怎么来。

    我唯唯诺诺了半天不敢直接写SPFA,最后一写居然就直接过了。

    将SPFA中带结构体表示当前点还可以访问的文化,每次进点时多花一个(O(N))处理就行了


    #include <cstdio>
    #include <cstring>
    #include <queue>
    using namespace std;
    const int N=104;
    int n,k,m,s,t;//k文化个数
    int c[N],g[N][N],head[N],w[N*N],to[N*N],next[N*N],cnt=0,dis[N];
    void add(int u,int v,int ww){next[++cnt]=head[u];to[cnt]=v;w[cnt]=ww;head[u]=cnt;}
    struct node
    {
        int from,is[N];
    };
    queue <node > q;
    void spfa()
    {
        node mes;
        for(int i=1;i<=k;i++)
            mes.is[i]=g[c[s]][i];
        mes.from=s;
        mes.is[c[s]]=0;
        q.push(mes);
        memset(dis,0x3f,sizeof(dis));
        dis[s]=0;
        while(!q.empty())
        {
            node tt=q.front();
            q.pop();
            for(int i=head[tt.from];i;i=next[i])
            {
                int v=to[i];
                if(tt.is[c[v]]&&dis[tt.from]+w[i]<dis[v])
                {
                    node tmp=tt;
                    dis[v]=dis[tt.from]+w[i];
                    for(int j=1;j<=k;j++)
                        if(!g[c[v]][j])
                            tmp.is[j]=0;
                    tmp.is[c[v]]=0;
                    tmp.from=v;
                    q.push(tmp);
                }
            }
        }
        if(dis[t]==0x3f3f3f3f) printf("-1
    ");
        else printf("%d
    ",dis[t]);
    }
    int main()
    {
        scanf("%d%d%d%d%d",&n,&k,&m,&s,&t);
        for(int i=1;i<=n;i++) scanf("%d",c+i);
        for(int i=1;i<=k;i++)
            for(int j=1;j<=k;j++)
            {
                scanf("%d",&g[j][i]);
                g[j][i]^=1;
            }
        int u,v,ww;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%d",&u,&v,&ww);
            add(u,v,ww),add(v,u,ww);
        }
        spfa();
        return 0;
    }
    
    

    2018.6.17

  • 相关阅读:
    使用CustomValidate自定义验证控件
    C#中金额的大小写转换
    Andriod出错之Unable to build: the file dx.jar was not loaded from the SDK folder!
    VC 编写的打字练习
    机房工作笔记Ping只有单向通
    web服务协同学习笔记(1)
    Dll 学习3 将MDI子窗口封装在DLL中
    机房工作学习文件共享
    Andriod出错之Failed to find an AVD compatible with target 'Android 2.2'
    Andriod出错之wrapper was not properly loaded first
  • 原文地址:https://www.cnblogs.com/butterflydew/p/9193694.html
Copyright © 2020-2023  润新知