zoukankan      html  css  js  c++  java
  • 洛谷 P1078 文化之旅(CODEVS 1316)

    题目描述

    有一位使者要游历各国,他每到一个国家,都能学到一种文化,但他不愿意学习任何一

    种文化超过一次(即如果他学习了某种文化,则他就不能到达其他有这种文化的国家)。不

    同的国家可能有相同的文化。不同文化的国家对其他文化的看法不同,有些文化会排斥外来

    文化(即如果他学习了某种文化,则他不能到达排斥这种文化的其他国家)。

    现给定各个国家间的地理关系,各个国家的文化,每种文化对其他文化的看法,以及这

    位使者游历的起点和终点(在起点和终点也会学习当地的文化),国家间的道路距离,试求

    从起点到终点最少需走多少路。

    输入输出格式

    输入格式:

    第一行为五个整数 N,K,M,S,T,每两个整数之间用一个空格隔开,依次代表国家

    个数(国家编号为 1 到 N),文化种数(文化编号为 1 到 K),道路的条数,以及起点和终点

    的编号(保证 S 不等于 T);

    第二行为 N 个整数,每两个整数之间用一个空格隔开,其中第 i 个数 Ci,表示国家 i

    的文化为 Ci。

    接下来的 K 行,每行 K 个整数,每两个整数之间用一个空格隔开,记第 i 行的第 j 个数

    为 aij,aij= 1 表示文化 i 排斥外来文化 j(i 等于 j 时表示排斥相同文化的外来人),aij= 0 表示

    不排斥(注意 i 排斥 j 并不保证 j 一定也排斥 i)。

    接下来的 M 行,每行三个整数 u,v,d,每两个整数之间用一个空格隔开,表示国家 u

    与国家 v 有一条距离为 d 的可双向通行的道路(保证 u 不等于 v,两个国家之间可能有多条

    道路)。

    输出格式:

    输出只有一行,一个整数,表示使者从起点国家到达终点国家最少需要走的距离数(如

    果无解则输出-1)。

    输入输出样例

    输入样例#1:
    2 2 1 1 2 
    1 2 
    0 1 
    1 0 
    1 2 10 
    
    输出样例#1:
    -1
    输入样例#2:
    2 2 1 1 2 
    1 2 
    0 1 
    0 0 
    1 2 10 
    输出样例#2:
    10

    说明

    输入输出样例说明1

    由于到国家 2 必须要经过国家 1,而国家 2 的文明却排斥国家 1 的文明,所以不可能到

    达国家 2。

    输入输出样例说明2

    路线为 1 -> 2

    【数据范围】

    对于 100%的数据,有 2≤N≤100 1≤K≤100 1≤M≤N2 1≤ki≤K 1≤u, v≤N 1≤d≤1000 S≠T 1≤S,T≤N

    NOIP 2012 普及组 第四题

    思路:

      还是最短路,但是多了几个判断:

      if(cul[now]!=cul[a[now][i]])      文化不同(因为同一文化不学两遍)

      if(f[cul[now]][cul[a[now][i]]])    now不排斥a[now][i]

      spfa一遍完成即可

    代码

      1.spfa+邻接表(学长的)

     1 #include<iostream>//AC
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<queue>
     5 using namespace std;
     6 const int N=101;
     7 const int K=101;
     8 const int M=10001;
     9 int n,k,m,s,t;
    10 int cal[N];
    11 bool f[K][K];//文化排斥\
    12 (f[i][j]标记为TRUE则学会j文化的外来人不能到拥有i文化的国家) 
    13 struct node{
    14     int next,to,v;
    15 }q[M];
    16 int cnt,head[N],dis[N];
    17 void add_edge(int u,int v,int d)//建边(链表存储) 
    18 {
    19     q[++cnt].to=v;
    20     q[cnt].next=head[u];
    21     head[u]=cnt;
    22     q[cnt].v=d;
    23 }
    24 int main()
    25 {
    26     cin>>n>>k>>m>>s>>t;
    27     for(int i=1;i<=n;i++){
    28         cin>>cal[i];//各国文化 
    29     }
    30     for(int i=1;i<=k;i++){
    31         for(int j=1;j<=k;j++){
    32             int s;cin>>s;
    33             if(s){//拥有i文化的国家排斥j文化的外来人 
    34                 f[i][j]=true;
    35             }
    36         }
    37     }
    38     for(int i=1;i<=m;i++){
    39         int u,v,d;
    40         cin>>u>>v>>d;
    41         add_edge(u,v,d);//u到v建一条单向边 
    42     }
    43     //↓模板 
    44     memset(dis,0x7f,sizeof(dis));
    45     int maxx=dis[1];
    46     dis[s]=0;
    47     queue<int>p;
    48     p.push(s);
    49     while(!p.empty()){
    50         int now=p.front();
    51         p.pop();
    52         for(int i=head[now];i;i=q[i].next){
    53             if(!f[cal[q[i].to]][cal[now]])
    54             if(cal[now]!=cal[q[i].to])
    55             if(dis[q[i].to]>dis[now]+q[i].v){
    56                 dis[q[i].to]=dis[now]+q[i].v;
    57                 p.push(q[i].to);
    58             }
    59         }
    60     }
    61     if(dis[t]<maxx)cout<<dis[t]<<endl;
    62     else cout<<"-1"<<endl;
    63     //↑模板 
    64 }
    answer1

      2.邻接表

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstring>
     4 using namespace std;
     5 int n,k,m,s,t,u,v,d,num[102];
     6 int cul[102],dis[102][102],mdis[102],que[102],edge[102][102];
     7 bool rej[102][102];//reject
     8 bool vis[102];
     9 void spfa(int x)
    10 {
    11     int head=0,tail=1,tp;
    12     que[0]=x;
    13     vis[x]=1;
    14     mdis[x]=0;
    15     while(head<tail)
    16     {
    17         tp=que[head++];
    18         vis[tp]=0;
    19         for(int i=1;i<=num[tp];i++)
    20         {
    21           int next=edge[tp][i];
    22           if(cul[tp]!=cul[next] && rej[cul[next]][cul[tp]])
    23           if(mdis[next]>mdis[tp]+dis[tp][next])
    24           {
    25               mdis[next]=mdis[tp]+dis[tp][next];
    26               if(!vis[next])
    27               {
    28                   que[tail++]=next;
    29                   vis[next]=1;
    30             }
    31           }
    32         }
    33     }
    34 }
    35 int main()
    36 {
    37     scanf("%d%d%d%d%d",&n,&k,&m,&s,&t);
    38     memset(dis,0x7f,sizeof(dis));
    39     memset(mdis,0x7f,sizeof(mdis));
    40     int maxn=mdis[t];
    41     for(int i=1;i<=n;i++)
    42       scanf("%d",&cul[i]);
    43     for(int i=1;i<=k;i++)
    44       for(int j=1;j<=k;j++)
    45       {
    46           int a;scanf("%d",&a);
    47           if(i!=j && a==0)//i不排斥j 
    48             rej[i][j]=1;
    49       }
    50     for(int i=1;i<=m;i++)
    51     {
    52         scanf("%d%d%d",&u,&v,&d);
    53         if(rej[cul[v]][cul[u]])//如果v不排斥u文化,则u可以到v 
    54         {
    55           dis[u][v]=min(dis[u][v],d);
    56           edge[u][++num[u]]=v;
    57         }
    58         if(rej[cul[u]][cul[v]])//同上 
    59         {
    60           dis[v][u]=min(dis[v][u],d);
    61           edge[v][++num[v]]=u;
    62         }
    63     }
    64     spfa(s);
    65     if(mdis[t]<maxn)
    66       printf("%d",mdis[t]);
    67     else
    68       printf("-1");
    69     return 0;
    70 }
    answer2

    无心插柳柳成荫才是美丽
    有哪种美好会来自于刻意
    这一生波澜壮阔或是不惊都没问题
    只愿你能够拥抱那种美丽

  • 相关阅读:
    springboot 前后端分离开发 从零到整(三、登录以及登录状态的持续)
    鼠标跟随
    sublime_text编辑器下载安装使用
    实现el-dialog的拖拽,全屏,缩小功能
    vue 动态添加路由 require.context()
    Vue JsonView 树形格式化代码插件
    利用vue-gird-layout 制作可定制桌面 (二)
    利用vue-gird-layout 制作可定制桌面 (一)
    通过js 实现 向页面插入js代码并生效,和页面postMessage通讯
    简单实现一个ES5 Vue Dialog 插件
  • 原文地址:https://www.cnblogs.com/SovietPower/p/6722810.html
Copyright © 2011-2022 走看看