蓝桥杯 文化之旅 图论 待复习

问题描述
  有一位使者要游历各国,他每到一个国家,都能学到一种文化,但他不愿意学习任何一种文化超过一次(即如果他学习了某种文化,则他就不能到达其他有这种文化的国家)。不同的国家可能有相同的文化。不同文化的国家对其他文化的看法不同,有些文化会排斥外来文化(即如果他学习了某种文化,则他不能到达排斥这种文化的其他国家)。
  现给定各个国家间的地理关系,各个国家的文化,每种文化对其他文化的看法,以及这位使者游历的起点和终点(在起点和终点也会学习当地的文化),国家间的道路距离,试求从起点到终点最少需走多少路。
输入格式
  第一行为五个整数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)。
样例输入
2 2 1 1 2
1 2
0 1
1 0
1 2 10
样例输出
-1
输入输出样例说明
  由于到国家2必须要经过国家1,而国家2的文明却排斥国家1的文明,所以不可能到达国家2。
样例输入
2 2 1 1 2
1 2
0 1
0 0
1 2 10
样例输出
10
输入输出样例说明
  路线为1 -> 2。
数据规模和约定
  对于20%的数据,有2≤N≤8,K≤5;
  对于30%的数据,有2≤N≤10,K≤5;
  对于50%的数据,有2≤N≤20,K≤8;
  对于70%的数据,有2≤N≤100,K≤10;
  对于100%的数据,有2≤N≤100,1≤K≤100,1≤M≤ N^2,1≤ki≤K,1≤u, v≤N,1≤d≤1000,S≠T,1 ≤S, T≤N。
图论的题目还不会做,先记录下题目备忘,之后复习。
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<set>
 5 #include<cmath>
 6 #include<algorithm>
 7 using namespace std;
 8 
 9 const int N=110,K=110;
10 int c[N],cultrul[K],graph[N][N],vis[N],a[N][N];
11 int n,k,m,s,t;
12 long long res=-1;
13 set<int>cu;
14 
15 void dfs(int next,long long sum)
16 {
17     if(res!=-1 && sum>res) return ;
18     if(next==s)
19     {
20         if(res==-1) res=sum;
21         else res=min(res,sum);//记录更短的路径
22         return ;    
23     } 
24     for(int i=1;i<=n;i++)
25     {
26         //没有来过这个国家  路径走得通  没有学习过这类文化  
27         if(!vis[i] && graph[i][next] && cultrul[c[i]]==false)
28         {
29             bool ok=true;
30             for(set<int>::iterator it=cu.begin();it!=cu.end();it++)//枚举后面国家文化类型 
31             {
32                 if(a[c[i]][*it])//如果当前国家文化和后继国家文化冲突 
33                 {
34                     ok=false;
35                     break;
36                 }
37             }
38             if(ok)
39             {
40                 vis[i]=true;
41                 cultrul[c[i]]=true;
42                 cu.insert(c[i]);
43                 dfs(i,sum+graph[i][next]);
44                 vis[i]=false;
45                 cultrul[c[i]]=false;
46                 cu.erase(c[i]);
47             }
48         }   
49     } 
50 } 
51 int main(void)
52 {
53     //freopen("D:\input6.txt","r",stdin);
54     int u,v,d;
55     cin>>n>>k>>m>>s>>t;
56     for(int i=1;i<=n;i++) cin>>c[i];
57     for(int i=1;i<=k;i++)
58     {
59         for(int j=1;j<=k;j++) cin>>a[i][j];
60     }
61     for(int i=1;i<=m;i++)
62     {
63         cin>>u>>v>>d;
64         if(graph[u][v]==0) graph[u][v]=graph[v][u]=d;
65         else if(graph[u][v]>d)
66         {
67             graph[u][v]=graph[u][v]=d;
68         }
69     }
70     
71     vis[t]=true;//访问过这个国家 
72     cultrul[c[t]]=true;//学习了这种文化 
73     cu.insert(c[t]); 
74     dfs(t,0);
75     cout<<res;
76     return 0;
77 } 

转载自https://blog.dotcpp.com/a/60688-5

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cstdlib>
 5 using namespace std;
 6 const int Inf=100000010;
 7 int n,m,k,s,t;
 8 int k1=0,sum=0,ans=Inf;
 9 int con[110],head[20010],fig[110][110];//con[i]=j表示第i个国家冲突第j种文化 fig[i][j]表示i j文化关系 
10 bool road[110],exp[110],flag=false;//road表示已访问的国家 exp表示已访问的文化 
11 struct node{
12     int to,next,w;
13 }e[20010];
14 void add(int u,int v,int w)
15 {
16     k1++;
17     e[k1].next=head[u];
18     e[k1].to=v;
19     e[k1].w=w;
20     head[u]=k1;
21 }
22 bool judge(int x)
23 {
24   if(road[x] || exp[con[x]]) return false;
25    for(int i=1;i<=k;i++)
26     if(exp[i]&&fig[con[x]][i]==1||fig[con[t]][con[x]]==1||fig[con[t]][i]) return false;
27     //后两个判断表明如果终点的文化冲突已经学过的文化和访问次国家的文化 则return false 
28      return true;
29 }
30 void dfs(int x,int sum)
31 {
32     bool ff=false;
33   if(x==t){
34       flag=true;
35       ans=min(ans,sum);
36       return ;
37   }
38   if(sum>=ans) return;//剪枝 
39   for(int i=head[x];i;i=e[i].next)
40   {
41       int p=e[i].to;
42       if(judge(p))
43       {
44         ff=true;//判断是否可以往下走 
45         road[p]=true,exp[con[p]]=true;
46         dfs(p,sum+e[i].w);
47         road[p]=false,exp[con[p]]=false;
48     }
49   }
50   if(ff==false){
51       printf("-1");//如果没有往下走 这直接打印-1并退出 
52       exit(0);
53   }
54 }
55 int main()
56 {
57     memset(road,false,sizeof(road));
58     memset(exp,false,sizeof(exp));
59     scanf("%d%d%d%d%d",&n,&k,&m,&s,&t);
60     for(int i=1;i<=n;i++) scanf("%d",&con[i]);
61     for(int i=1;i<=k;i++)
62      for(int j=1;j<=k;j++) 
63       scanf("%d",&fig[i][j]);
64     int x,y,z;
65     for(int i=1;i<=m;i++)
66     {
67       scanf("%d%d%d",&x,&y,&z);
68       sum+=z;
69       add(x,y,z);
70       add(y,x,z);
71     }  
72     exp[con[s]]=true;
73     dfs(s,0);
74     if(ans>sum||flag==false) printf("-1");
75     else printf("%d",ans);
76     return 0;
77 }
原文地址:https://www.cnblogs.com/fx1998/p/12731155.html