Safari Park

染色问题:先建图。然后给每个顶点涂色,就是把顶点编号改一下。然后针对每个顶点,判断相邻顶点编号是否和当前顶点编号一致,如果一致,说明颜色相同。
方法一:邻接表实现。由于邻接表只能存储终点编号(好像也可以在结构体里存储起始顶点编号,懒得改了),所以还要一个数组存放当前顶点编号。

#include <iostream>
#include <vector>
#include <set>
using namespace std;
const int maxv = 510;
int a[maxv];    //存放顶点的颜色,即动物种类。a[1]=3意为1号顶点颜色编号为3
struct node{
    int v;  //边终点颜色编号
};

vector<node> G[maxv];
set<int> st;
node no[maxv];  //存放当前顶点颜色编号



int main() {
    int n,r,k,m, v1, v2;
    scanf("%d%d%d", &n, &r, &k);
    for(int i=0; i<r; i++){
        scanf("%d%d", &v1, &v2);
        G[v1].push_back(node{v2});
        G[v2].push_back(node{v1});
    }
    scanf("%d", &m);
    //int v;
    for(int i=1; i<=m; i++){
        for(int j=1; j<=n; j++){
            scanf("%d", &a[j]);
            no[j].v = a[j];
            st.insert(a[j]);
        }
        if(st.size()>k)         printf("Error: Too many species.\n");
        else if(st.size()<k)    printf("Error: Too few species.\n");
        else{
            for(int j=1; j<=n; j++){//给顶点涂色
                for(int q=0; q<G[j].size(); q++){
                    int v = G[j][q].v;
                    G[j][q].v = a[v];
                }
            }
            bool flag = true;
            for(int j=1; j<=n; j++){//判断相邻顶点颜色是否相同
                for(int q=0; q<G[j].size(); q++){
                    v1 = no[j].v;
                    v2 = G[j][q].v;
                    if(v1==v2){
                        flag = false;
                        break;
                    }
                }
                if(flag==false) break;
            }
            if(flag)    printf("Yes\n");
            else    printf("No\n");
        }
        st.clear();
    }
    return 0;
}

方法二:邻接矩阵实现。由于最大顶点只有500个,寻找每个相邻顶点最大复杂度为O(250000),这是可以接受的。G[1][3]=1,第1,3号顶点相邻,要涂色的话只需把1,3改为要涂的颜色即可。假设1号顶点涂5,3号顶点也涂5,只需另创建一个邻接矩阵让G2[5][5]=1即可。然后对G2进行处理。

#include <iostream>
#include <vector>
#include <algorithm>
#include <set>
using namespace std;
const int maxv = 510;
int G[maxv][maxv], G2[maxv][maxv];
int a[maxv];  //存储每个顶点的颜色
set<int> st;

int main() 
{
    fill(G[0], G[0]+maxv*maxv, 0);
    fill(G2[0], G2[0]+maxv*maxv, 0);
    int n,r,k,m, v1, v2;
    scanf("%d%d%d", &n, &r, &k);
    for(int i=0; i<r; i++){
        scanf("%d%d", &v1, &v2);
        G[v1][v2] = G[v2][v1] = 1;
    }
    scanf("%d", &m);
    //int v;
    for(int i=1; i<=m; i++){
        for(int j=1; j<=n; j++){
            scanf("%d", &a[j]);
            st.insert(a[j]);
        }
        if(st.size()>k)         printf("Error: Too many species.\n");
        else if(st.size()<k)    printf("Error: Too few species.\n");
        else{
            bool flag = true;
            for(int j=1; j<=n; j++){
                for(int q=1; q<=n; q++){
                	//如果相邻顶点涂色相同
                    if(G[j][q]==1 && a[j]==a[q])    flag = false;
                }
            }
            if(flag)    printf("Yes\n");
            else    printf("No\n");
        }
        st.clear();
        fill(G2[0], G2[0]+maxv*maxv, 0);
    }
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值