Codeforces Gym 101158 F. Three Kingdoms of Bourdelot

来源:互联网 发布:淘宝举证是什么意思 编辑:程序博客网 时间:2024/06/05 15:25

题意

有多个文档。 每个文档都有多行家谱信息。 有两种类型的文档: 正和负, 每行是一对 x, y,

  • 如果文档为正: x 是 y 的祖先
  • 如果文档为负: x 不是 y 的祖先

每个文档都可以有正面或负面的理解。 如果文档数量 n 和两个人 p, q 是给定的, 确定是否有一种组合(确定每篇文档的正负),使得满足 p 是 q 的祖先。

解题思路

数据结构。

  • 存储 x, y 属于哪几篇文档,
  • 存储每篇文档包含的 x, y
  • 记录二维数组 isAnc[i][j]=1 表示 i 是 j 的祖先

对于已确定 x, y, 其对应的文档都应该是正面的,即对应文档中的所有记录均为正确的。根据这些记录的正确性及原本的祖孙关系,产生新的 x, y ,判断是否存在 isAnc[i][j] = isAnc[j][i] = 1 的情况,存在为 No ,否则一定为 Yes

代码

#include<bits/stdc++.h>using namespace std;const int NAME = 300+10;const int N = 100000 + 10;string p, q, a, b;int n, idx;vector<pair<int, int> > g[1010];map<string, int> str2int;vector<int> belg[NAME][NAME];bool isAnc[NAME][NAME], vis[1010];bool dfs(int ancestor, int son);bool setAncestor(int ancestor, int son){    if(isAnc[son][ancestor] == 1)   return false;    isAnc[ancestor][son] = 1;    for(int i=1;i<=idx;i++)    {        if(isAnc[i][ancestor] == 1)        {            if(isAnc[son][i] == 1)                return false;            else {                isAnc[i][son] = 1;                if(dfs(i, son) == false)    return false;            }        }        if(isAnc[son][i] == 1)        {            if(isAnc[i][ancestor] == 1) return false;            else {                isAnc[ancestor][i] = 1;                if(dfs(ancestor, i) == false)   return false;            }        }    }    return true;}bool dfs(int ancestor, int son){    for(int i=0, id;i<belg[ancestor][son].size();i++)    {        id = belg[ancestor][son][i];        if(vis[id]) continue;        vis[id] = 1;        for(int j=0;j<g[id].size();j++)        {            if(setAncestor(g[id][j].first, g[id][j].second) == false)                return false;            if(dfs(g[id][j].first, g[id][j].second) == false)                return false;        }    }    return true;}int main(){    cin>>p>>q;    str2int[p] = ++idx;    str2int[q] = ++idx;    scanf("%d", &n);    for(int i=1, m;i<=n;i++)    {        scanf("%d", &m);        for(int j=0;j<m;j++)        {            cin>>a>>b;            if(str2int.find(a) == str2int.end())                str2int[a] = ++idx;            if(str2int.find(b) == str2int.end())                str2int[b] = ++idx;            belg[str2int[a]][str2int[b]].push_back(i);            g[i].push_back(make_pair(str2int[a], str2int[b]));        }    }    isAnc[str2int[p]][str2int[q]] = 1;    if(dfs(str2int[p], str2int[q]))    {        for(int i=1;i<=idx;i++)        for(int j=i+1;j<=idx;j++)            if(isAnc[i][j] == isAnc[j][i] && isAnc[i][j] == 1)            {                printf("No\n");                return 0;            }        printf("Yes\n");    }    else    printf("No\n");}
原创粉丝点击