您的位置:首页 > 其它

Codeforces Gym 101158 F. Three Kingdoms of Bourdelot

2017-07-09 15:06 501 查看

题意

有多个文档。 每个文档都有多行家谱信息。 有两种类型的文档: 正和负, 每行是一对
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");
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: