zoukankan      html  css  js  c++  java
  • Vijos P1794 文化之旅

      标签:                                         搜索图结构 最短路                                    NOIP普及组2012


        

     题目链接 : 点这里 。                    

    这是一道最短路题目,一开始当做暴搜题目来做TLE很多次,想要优化却改成WrongAnswer。最后用SPFA 过了。

    思路:最短路,松弛判断的时候判断文化之间是否排斥,用一个二维数组记录当前城市那些文化已经学习;这一个状态的文化 = 上一个状态的文化 + 此次学习的文化。dfs 会比较慢。


     

    #include<stdio.h>
    #include<string.h>
    #include<iostream>
    #include<algorithm>
    #include<queue>
    
    using namespace std;
    typedef long long int LL;
    const int INF=2e9+1e8;
    const int MAXSIZE=10000;
    
    
    int N,K,M,S,T; //题目信息
    int first[MAXSIZE],knext[MAXSIZE],ntotal;  //邻接表,这是邻接表的数组存储方式;
    struct Edge
    {
        int s,t,val;
    };
    Edge edge[MAXSIZE];
    int cultrue[MAXSIZE][MAXSIZE],city_cul[MAXSIZE]; //前者 记录文化之间的排斥关系,后面的巨鹿某一个城市的文化
    bool learn[105][105]; //这个数组 下标 i,j  . 表示走到 i 号城市 j文化  是否学习,学习了为 true;
    
    void init()// 初始化邻接表;
    {
        memset(first,-1,sizeof(first)); 
        ntotal=0;
    }
    
    void addedge(int s,int t,int val) //添加边函数
    {
        edge[ntotal].s=s,edge[ntotal].t=t,edge[ntotal].val=val;
        knext[ntotal]=first[s];
        first[s]=ntotal;
        ntotal++;
    }
    bool check(int pre,int cul) //判断 前一个城市 pre 的文化
    {
        if(learn[pre][cul]) return false; // 如果当前文化之前已经学过 返回false
        for(int i=1; i<=K; i++)
        {
            if(learn[pre][i]==true&&cultrue[cul][i]) return false; //如果上一个状态学过的文化 与 当前要学的排斥 false
        }
        return true; //否则 true
    }
    int spfa() //下面是  SPFA 模板 不懂上面有链接或者百度;
    {
        queue<int>q;
        bool in_queue[200];
        int dis[200];
        for(int i=0; i<=110; i++)
            dis[i]=INF;
        memset(in_queue,0,sizeof(in_queue));
        memset(learn,0,sizeof(learn));
        dis[S]=0;
        q.push(S);
        in_queue[S]=1;
        learn[S][city_cul[S]]=1;
        while(!q.empty())
        {
            int k,x=q.front();
            q.pop();
            in_queue[x]=0;
            k=first[x];
            while(k+1)
            {
                int to=edge[k].t;
                if(dis[x]+edge[k].val<dis[to]&&check(x,city_cul[to]))
                {
                    learn[to][city_cul[to]]=true;
                    for(int jj=1;jj<=K;jj++)
                    {
                        if(learn[x][jj]) learn[to][jj]=1;
                        else learn[to][jj]=0;
                    }
                    dis[to]=dis[x]+edge[k].val;
                    if(!in_queue[to])
                    {
                        in_queue[to]=1;
                        q.push(to);
                    }
                }
                k=knext[k];
            }
        }
        if(dis[T]==INF) return -1;
        else return dis[T];
    }
    int main()
    {
        init();
        scanf("%d%d%d%d%d",&N,&K,&M,&S,&T);
        for(int i=1; i<=N; i++)
        {
            scanf("%d",&city_cul[i]);
        }
        for(int i=1; i<=K; i++)
        {
            for(int j=1; j<=K; j++)
                scanf("%d",&cultrue[i][j]);
        }
        for(int i=0; i<M; i++)
        {
            int s,t,w;
            scanf("%d%d%d",&s,&t,&w);
            addedge(s,t,w);
            addedge(t,s,w);
        }
        cout<<spfa()<<endl;
        return 0;
    }
    

  • 相关阅读:
    android常用的Application类
    Android一些问题的解决方案
    MakeFile相关
    Android源码与设计模式之notifyDataSetChanged()方法与观察者模式
    Activity启动模式与onNewIntent()简述
    (转)eval与迭代
    ADB命令
    其他常用工具类
    文件操作常用工具方法
    [TJOI2007] 可爱的质数
  • 原文地址:https://www.cnblogs.com/coded-ream/p/7207954.html
Copyright © 2011-2022 走看看