问题描述
角色授权 题目链接
解题思路
大模拟,每一次查询时检查关联的组和用户是否满足要求。
代码实现
#include<iostream>
#include<vector>
#include<unordered_map>
#include<set>
#include<queue>
using namespace std;
int n,m,q;
unordered_map<string,int> nametoidx;
struct character {
string name;
unordered_map<string,int> opMap;
unordered_map<string,int> typeMap;
unordered_map<string,int> resourceMap;
} characters[1010];
struct user {
string name;
set<string> group;
};
struct action {
user u;
string op ;
string type;
string resource;
} actions[5010];
unordered_map<string,set<string>> relation;
unordered_map<string,set<string>> groupmember;
void getuser(){
for(int i = 1; i <= n; i++) {
string name;
int nv;
cin >> name>>nv;
nametoidx[name] = i;
characters[i].name = name;
for(int j = 1; j <= nv; j++) {
string op;
cin >> op;
characters[i].opMap[op] = 1;
}
int no;
cin >> no;
for(int j = 1; j <= no; j++) {
string tp;
cin >> tp;
characters[i].typeMap[tp] = 1;
}
int nn;
cin >> nn;
for(int j = 1; j <= nn; j++) {
string rs;
cin >> rs;
characters[i].resourceMap[rs] = 1;
}
}
}
void getrelation() {
for(int i = 1; i <= m; i++) {
string name;
int ns;
cin >> name>> ns;
for(int j = 1; j<=ns; j++ ) {
char t;
string str;
cin >> t >> str;
if(t == 'u') {
relation[str].insert(name);
} else {
groupmember[str].insert(name);
}
}
}
}
void check(int i) {
string op,type,resource;
op = actions[i].op;
type = actions[i].type;
resource = actions[i].resource;
unordered_map<string,bool> st;
bool opflag = false;
bool typeflag = false;
bool resourceflag= false;
bool r = 0;
//判断三个是否有权限
for(auto grp : actions[i].u.group) {
//遍历组
// cout <<" check group "<<grp<<endl;
for(auto mem : groupmember[grp]) {
//遍历组的成员
if(!st.count(mem)) {
opflag = false;
typeflag = false;
resourceflag= false;
// cout << "check group "<<grp<<" member "<<mem<<endl;
int memidx = nametoidx[mem];
if(characters[memidx].opMap.count(op) || characters[memidx].opMap.count("*")) {
opflag =1;
}
if(characters[memidx].typeMap.count(type) || characters[memidx].typeMap.count("*")) {
typeflag =1;
}
if(characters[memidx].resourceMap.count(resource) || characters[memidx].resourceMap.size() == 0) {
resourceflag =1;
}
r = r | (opflag && typeflag && resourceflag);
st[mem] = 1;
}
}
}
queue<string> q;
q.push(actions[i].u.name);
while(q.size()) {
auto nm = q.front();
q.pop();
for(auto u : relation[nm]) {
// 从相关联的中找
// u是字符串
if(!st.count(u)) {
q.push(u);
opflag = false;
typeflag = false;
resourceflag= false;
int memidx = nametoidx[u];
if(characters[memidx].opMap.count(op) || characters[memidx].opMap.count("*")) {
opflag =1;
}
if(characters[memidx].typeMap.count(type) || characters[memidx].typeMap.count("*")) {
typeflag =1;
}
if(characters[memidx].resourceMap.count(resource) || characters[memidx].resourceMap.size() == 0) {
resourceflag =1;
}
r = r | (opflag && typeflag && resourceflag);
st[u] = 1;
}
}
}
if(r) {
cout <<1<<endl;
} else {
cout<<0<<endl;
}
}
void getaction() {
for(int i = 1; i <= q; i++) {
string name;
int ng;
cin >> name>> ng;
actions[i].u.name = name;
for(int j = 1; j<=ng; j++ ) {
string str;
cin >> str;
actions[i].u.group.insert(str);
}
string a,b,c;
cin >> a>>b>>c;
actions[i].op = a, actions[i].type = b, actions[i].resource=c;
check(i);
}
}
int main() {
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
cin >> n >> m >> q;
getuser();
getrelation();
getaction();
}
一些问题和踩到的坑
查询不用存到数组里,因为不同的查询是独立的。后面写了太长时间懒得改了,可能改了后能够快一点
访问成功需要关联的用户中三个条件同时满足
关联用户时建立的是一个有向边,因为建了无向边改了好久一直是50分
用ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)加速可以避免超时,不用的话只有70分
存关联的用户和组的时候可以用set或者map