大模拟,只要会用复杂一点的数据结构,就没问题。
同时要注意超时问题,我一开始用的全都是vector就嗯顺序遍历搜操作、资源种类和资源清单,很自然地超时了,,后来全都换成set,之后直接.count(),又省事又快!
#include<iostream>
#include<vector>
#include<set>
#include<unordered_map>
using namespace std;
#pragma GCC optimize(2)
struct User{
string name;
set<string> op;
set<string> cat;
set<string> list;
};
// 记录某些用户或组关联了哪些角色
// 实际上组和用户没必要区分,统一看作用户
unordered_map<string, vector<int>> to_users;
int main(){
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int n, m, q;
cin >> n >> m >> q;
vector<User> users(n);
// Users
string tmp;
for(int i = 0; i < n; i ++){
cin >> tmp;
users[i].name = tmp;
int nv, no, nn;
// operations
cin >> nv;
while(nv--){
cin >> tmp;
users[i].op.insert(tmp);
}
// category
cin >> no;
while(no--){
cin >> tmp;
users[i].cat.insert(tmp);
}
// list
cin >> nn;
while(nn--){
cin >> tmp;
users[i].list.insert(tmp);
}
}
// 将用户或组绑定已有的角色
while(m--){
//
cin >> tmp;
int idx = -1;
for(int i = 0; i < users.size(); i ++){
if(users[i].name == tmp){
idx = i;
break;
}
}
int ns;
cin >> ns;
string t1, t2;
while(ns--){
cin >> t1 >> t2;
// push_back的是角色在users数组中的下标
// 把用户和组都看做成用户,不区分身份,因此t1没用
to_users[t2].push_back(idx);
}
}
while(q--){
cin >> tmp;
int ng;
cin >> ng;
vector<string> group;
// 加入关联的用户组(包含自己以及关联的用户和组)
group.push_back(tmp);
while(ng--) {
cin >> tmp;
group.push_back(tmp);
}
// check tmp1 tmp2 tmp3
string tmp1, tmp2, tmp3;
cin >> tmp1 >> tmp2 >> tmp3;
bool flag1 = false, flag2 = flag1, flag3 = flag1;
// 之后就是看组中这些用户关联的角色们是否有权限了
// 满足一个就break,否则就重置三个flag
for(int i = 0; i < group.size(); i ++){
int n = to_users[group[i]].size();
for(int j = 0; j < n; j ++){
if(users[to_users[group[i]][j]].op.count(tmp1) || users[to_users[group[i]][j]].op.count("*"))
flag1 = true;
if(users[to_users[group[i]][j]].cat.count(tmp2) || users[to_users[group[i]][j]].cat.count("*"))
flag2 = true;
if(users[to_users[group[i]][j]].list.size() == 0) flag3 = true;
else{
if(users[to_users[group[i]][j]].list.count(tmp3))
flag3 = true;
}
if(flag1 && flag2 && flag3) break;
else{
flag1 = false;
flag2 = flag1;
flag3 = flag1;
}
}
if(flag1 && flag2 && flag3) break;
}
if(flag1 && flag2 && flag3) cout << 1 << endl;
else cout << 0 << endl;
}
}