QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#360241 | #5034. >.< | Strywr | Compile Error | / | / | C++20 | 6.2kb | 2024-03-21 15:54:05 | 2024-03-21 15:54:05 |
Judging History
answer
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
inline ll read() {
ll x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {
if (ch == '-') f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
x = (x << 1) + (x << 3) + (ch ^ '0');
ch = getchar();
}
return x * f;
}
const int N = 4e5 + 10; const ll inf = 1e18;
int n, m, k; int fail[N], tot; vector<pair<int, int> > e[N];
unordered_map<int, int> trie[N]; vector<int> son[N]; int a[N];
int ed[N], nd[N]; vector<int> ef[N];
void insert(int len) {
int x = 0;
for (int i = 1; i <= len; i++) {
if (!trie[x][a[i]]) trie[x][a[i]] = ++tot, son[x].push_back(a[i]);
x = trie[x][a[i]]; nd[x] = a[i];
} ed[x] = 1;
}
void getfail() {
queue<int> q;
for (int i = 1; i <= n; i++) q.push(i);
while (q.size()) {
int u = q.front(); q.pop();
for (auto i : son[u]) {
int x = trie[u][i]; int nw = fail[u];
while (!trie[nw].count(i) && nw) nw = fail[nw];
fail[x] = trie[nw][i]; q.push(x); //!!!!!!!!!只要访问了就一定会建立出来,.count也是1了
}
}
}
int sz[N], id[N], num, ch[N]; bool vis[N];
void gethf(int u) {
if (ch[id[u]]) return; //自己不合法,整个子树也不合法了 ,
// 我们称每个路径的最后一个元素所在的点为不合法点,所有不合法点fail子树的点一定也不合法(因为能通过跳fail标记到不合法点)
//而且这些所有不合法点在trie树上的子树的点也一定不合法,因为子树里的点完全包含祖先的字符串,
//所以如果到达了子树,说明一定包含祖先的字符串,一定不可以
vis[u] = 1;
for (auto i : son[u]) {
int v = trie[u][i]; gethf(v);
}
}
void dfs(int u) {
sz[u] = 1; id[u] = ++num;
for (auto v : ef[u]) dfs(v), sz[u] += sz[v];
}
struct Seg {
int lc, rc, sum, v, w; //1~tot
}tr[N*20]; int cur, rt[N];//一共2e5个点 ,4e5次单点插入(1~n节点插入的原边 + n+1~tot节点插入的trie树上的边) 一共4e5
void pushup(int nw) {
tr[nw].sum = tr[tr[nw].lc].sum + tr[tr[nw].rc].sum;
}
void insert(int &p, int q, int l, int r, int x, int v, int w) {
p = ++cur; tr[p] = tr[q];
if (l == r) {
tr[p].sum = 1; tr[p].w = w; tr[p].v = v; return;
} int mid = (l + r) >> 1;
if (x <= mid) insert(tr[p].lc, tr[q].lc, l, mid, x, v, w);
else insert(tr[p].rc, tr[q].rc, mid + 1, r, x, v, w);
pushup(p);
}
unordered_map<pair<int, int>, int> ex;
void addedge() {
queue<int> q;
for (int i = 1; i <= n; i++) {
if (vis[i]) {
for (auto nw : e[i]) {
int to = trie[i].count(nw.first) ? trie[i][nw.first] : nw.first;
insert(rt[i], rt[i], 1, n, nw.first, to, nw.second);
} q.push(i);
}
}
while (q.size()) {
int u = q.front(); q.pop();
for (auto i : son[u]) {
int x = trie[u][i]; if (!vis[x]) continue;
rt[x] = rt[fail[x]];
//!!!!!!!!!!!!!!!!!!!!!!!!可持久化线段树的下标不能是1~tot,这些AC自动机上的点
//而应该是1~n, 表示原图中的点。因为比如下面的样例,fail[5]=2,5从fail[5]里面继承了一个2->3的边
//继承过了也就是5链接到3,但是我们发现6对应的也是3,所以5实际上应该连接到6,如果我们直接加边,那么5->3
//的边就删除不了,而如果我们用1~n, 那么5->3 和 5->6的边都存在于下标2,可以直接覆盖
//每个叶子维护一个v,w 表示这个终点在AC自动机上对应的点,以及边权
// for (auto nw : e[nd[x]]) { //!!!!!!!!!!!!nw.first是原图的点,不是AC自动机的,而我们的连边是AC自动机的
// if (!trie[x].count(nw.first) && x > n) continue; //x <= n的那几个点在这个时候也要连边
// int to = trie[x].count(nw.first) ? trie[x][nw.first] : nw.first;
// if (vis[to]) insert(rt[x], rt[x], 1, tot, to, nw.second);
// } q.push(x);
//!!!!!!!!!!!!!!!应该是nd[x],因为nd[x]是原图的点,x是AC自动机上面的
//!!!!!!!!!!!!!!!!!!!!不能每个点遍历一遍这个点的出边,因为AC自动机上面很多个点都对应原图中的一个点,如果这个点出边多,就废了
for (auto nw : son[x]) {//????????????????nw=?
int to = trie[x][nw];
if (ex.count(make_pair(nd[x], nd[to]))) insert(rt[x], rt[x], 1, n, nw, to, ex[make_pair(nd[x], nd[to])]);
//!!!这里不能加vis[to],因为我们链接向这里,是为了删除原来的边,dij的时候判断掉!vis的点即可
}
q.push(x);
}
}
}
ll dis[N]; bool viss[N];
struct qnode {
int u; ll d;
qnode(int uu, ll dd) {
u = uu; d = dd;
}
friend bool operator < (qnode a, qnode b) {
return a.d > b.d;
}
}; priority_queue<qnode> q;
void update(int nw, int l, int r, ll d) {
if (l == r) {
int x = tr[nw].v;
if (vis[x] && dis[x] > d + tr[nw].w) {
dis[x] = d + tr[nw].w; q.push(qnode(x, dis[x]));
} tr[nw].sum = 0; return;
} int mid = (l + r) >> 1;
if (tr[tr[nw].lc].sum) update(tr[nw].lc, l, mid, d);
if (tr[tr[nw].rc].sum) update(tr[nw].rc, mid + 1, r, d);
pushup(nw);
}
void dij() {
if (!vis[1]) {cout << -1; exit(0);}
for (int i = 1; i <= tot; i++) dis[i] = inf;
dis[1] = 0; q.push(qnode(1, 0));
while (q.size()) {
int u = q.top().u; q.pop();
if (viss[u]) continue;
viss[u] = 1; update(rt[u], 1, n, dis[u]);
} ll ans = inf;
for (int i = 1; i <= tot; i++) {
if (nd[i] == n && vis[i]) {
ans = min(ans, dis[i]);
}
}
if (ans == inf) ans = -1;
cout << ans;
}
//!!!!!!!!!!!!!!!!!!!!++cur
int main() {
n = read(), m = read(), k = read();
for (int i = 1; i <= n; i++) trie[0][i] = ++tot, son[0].push_back(i), nd[tot] = i;
for (int i = 1; i <= m; i++) {
int u = read(), v = read(), w = read();
e[u].push_back(make_pair(v, w)); ex[make_pair(u, v)] = w;
}
for (int i = 1; i <= k; i++) {
int p = read();
for (int j = 1; j <= p; j++) a[j] = read();
insert(p);
} getfail(); for (int i = 1; i <= tot; i++) ef[fail[i]].push_back(i); dfs(0);
for (int i = 1; i <= tot; i++) { //1~n是自己加入的单点
if (ed[i]) ch[id[i]]++, ch[id[i]+sz[i]]--; //子树标记
} for (int i = 1; i <= num; i++) ch[i] += ch[i-1];
gethf(0); addedge(); dij();
return 0;
}
/*
4 4 1
1 2 1
2 3 1
3 4 1
3 2 1
4 1 2 3 4
*/
Details
answer.code:71:36: error: use of deleted function ‘std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map() [with _Key = std::pair<int, int>; _Tp = int; _Hash = std::hash<std::pair<int, int> >; _Pred = std::equal_to<std::pair<int, int> >; _Alloc = std::allocator<std::pair<const std::pair<int, int>, int> >]’ 71 | unordered_map<pair<int, int>, int> ex; | ^~ In file included from /usr/include/c++/13/unordered_map:41, from /usr/include/c++/13/functional:63, from /usr/include/x86_64-linux-gnu/c++/13/bits/stdc++.h:53, from answer.code:1: /usr/include/c++/13/bits/unordered_map.h:148:7: note: ‘std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map() [with _Key = std::pair<int, int>; _Tp = int; _Hash = std::hash<std::pair<int, int> >; _Pred = std::equal_to<std::pair<int, int> >; _Alloc = std::allocator<std::pair<const std::pair<int, int>, int> >]’ is implicitly deleted because the default definition would be ill-formed: 148 | unordered_map() = default; | ^~~~~~~~~~~~~ /usr/include/c++/13/bits/unordered_map.h:148:7: error: use of deleted function ‘std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::_Hashtable() [with _Key = std::pair<int, int>; _Value = std::pair<const std::pair<int, int>, int>; _Alloc = std::allocator<std::pair<const std::pair<int, int>, int> >; _ExtractKey = std::__detail::_Select1st; _Equal = std::equal_to<std::pair<int, int> >; _Hash = std::hash<std::pair<int, int> >; _RangeHash = std::__detail::_Mod_range_hashing; _Unused = std::__detail::_Default_ranged_hash; _RehashPolicy = std::__detail::_Prime_rehash_policy; _Traits = std::__detail::_Hashtable_traits<true, false, true>]’ In file included from /usr/include/c++/13/bits/unordered_map.h:33: /usr/include/c++/13/bits/hashtable.h:530:7: note: ‘std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::_Hashtable() [with _Key = std::pair<int, int>; _Value = std::pair<const std::pair<int, int>, int>; _Alloc = std::allocator<std::pair<const std::pair<int, int>, int> >; _ExtractKey = std::__detail::_Select1st; _Equal = std::equal_to<std::pair<int, int> >; _Hash = std::hash<std::pair<int, int> >; _RangeHash = std::__detail::_Mod_range_hashing; _Unused = std::__detail::_Default_ranged_hash; _RehashPolicy = std::__detail::_Prime_rehash_policy; _Traits = std::__detail::_Hashtable_traits<true, false, true>]’ is implicitly deleted because the default definition would be ill-formed: 530 | _Hashtable() = default; | ^~~~~~~~~~ /usr/include/c++/13/bits/hashtable.h:530:7: error: use of deleted function ‘std::__detail::_Hashtable_base<_Key, _Value, _ExtractKey, _Equal, _Hash, _RangeHash, _Unused, _Traits>::_Hashtable_base() [with _Key = std::pair<int, int>; _Value = std::pair<const std::pair<int, int>, int>; _ExtractKey = std::__detail::_Select1st; _Equal = std::equal_to<std::pair<int, int> >; _Hash = std::hash<std::pair<int, int> >; _RangeHash = std::__detail::_Mod_range_hashing; _Unused = std::__detail::_Default_ranged_hash; _Traits = std::__detail::_Hashtable_traits<true, false, true>]’ In file included from /usr/include/c++/13/bits/hashtable.h:35: /usr/include/c++/13/bits/hashtable_policy.h:1710:7: note: ‘std::__detail::_Hashtable_base<_Key, _Value, _ExtractKey, _Equal, _Hash, _RangeHash, _Unused, _Traits>::_Hashtable_base() [with _Key = std::pair<int, int>; _Value = std::pair<const std::pair<int, int>, int>; _ExtractKey = std::__detail::_Select1st; _Equal = std::equal_to<std::pair<int, int> >; _Hash = std::hash<std::pair<int, int> >; _RangeHash = std::__detail::_Mod_range_hashing; _Unused = std::__detail::_Default_ranged_hash; _Traits = std::__detail::_Hashtable_traits<true, false, true>]’ is implicitly deleted because the default definition would be ill-formed: 1710 | _Hashtable_base() = default; | ^~~~~~~~~~~~~~~ /usr/include/c++/13/bits/hashtable_policy.h:1710:7: error: use of deleted function ‘std::__detail::_Hash_code_base<_Key, _Value, _ExtractKey, _Hash, _RangeHash, _Unused, __cache_hash_code>::_Hash_code_base() [with _Key = std::pair<int, int>; _Value = std::pair<const std::pair<int, int>, int>; _ExtractKey = std::__detail::_Select1st; _Hash = std::hash<std::pair<int, int> >; _RangeHash = std::__detail::_Mod_range_hashing; _Unused = std::__detail::_Default_ranged_hash; bool __cache_hash_code = true]’ /usr/include/c++/13/bits/hashtable_policy.h: In instantiation of ‘std::__detail::_Hashtable_ebo_helper<_Nm, _Tp, true>::_Hashtable_ebo_helper() [with int _Nm = 1; _Tp = std::hash<std::pair<int, int> >]’: /usr/include/c++/13/bits/hashtable_policy.h:1297:7: required from here /usr/include/c++/13/bits/hashtable_policy.h:1214:49: error: use of deleted function ‘std::hash<std::pair<int, int> >::hash()’ 1214 | _Hashtable_ebo_helper() noexcept(noexcept(_Tp())) : _Tp()...