【BZOJ1194】[HNOI2006]潘多拉的盒子【BFS】【SCC】【拓扑排序】【DAG最长路】【自动机】

来源:互联网 发布:linux sleep longer 编辑:程序博客网 时间:2024/04/30 10:29

【题目链接】

这题有毒orz。

判断两个自动机是否有升级关系,BFS一次就行了orz。两个自动机都从0开始,同时走0,同时走1。如果一个自动机到达输出点,而另一个没到达,那么没有升级关系。

然后根据升级关系建图,Tarjan缩点,然后跑DAG上最长路就行了。


注意一个强联通内都是互相有升级关系的,跑最长路时要取size而不是取1,WA了一发...

/* Pigonometry */#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int maxn = 55, maxm = maxn * maxn, maxq = 10000, maxs = 10000;int n, head[maxn], cnt, vis[maxn][maxn], clo;int dfn[maxn], low[maxn], belong[maxn], size[maxn], tot, sta[maxs], top;int dp[maxn], mp[maxn][maxn], du[maxn], q[maxq];bool ins[maxn];struct _edge {int v, next;} g[maxm << 1];struct _data {int x, y;};inline int iread() {int f = 1, x = 0; char ch = getchar();for(; ch < '0' || ch > '9'; ch = getchar()) f = ch == '-' ? -1 : 1;for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';return f * x;}struct automaton {int n, m, trans[maxn][2];bool out[maxn];void read() {n = iread(); m = iread();for(int i = 1; i <= m; i++) out[iread()] = 1;for(int i = 0; i < n; i++) trans[i][0] = iread(), trans[i][1] = iread();}} A[maxn];inline void add(int u, int v) {g[cnt] = (_edge){v, head[u]};head[u] = cnt++;}inline bool bfs(int s, int d) {static _data q[maxq];clo++;int h = 0, t = 0; q[t++] = (_data){0, 0};vis[0][0] = clo;while(h != t) {_data u = q[h++];int x = u.x, y = u.y;if(A[s].out[x] && !A[d].out[y]) return 0;for(int i = 0; i < 2; i++) {int xx = A[s].trans[x][i], yy = A[d].trans[y][i];if(vis[xx][yy] != clo) {vis[xx][yy] = clo;q[t++] = (_data){xx, yy};}}}return 1;}inline void tarjan(int x) {dfn[x] = low[x] = ++clo;ins[sta[++top] = x] = 1;for(int i = head[x]; ~i; i = g[i].next) {int v = g[i].v;if(!dfn[v]) tarjan(v), low[x] = min(low[x], low[v]);else if(ins[v]) low[x] = min(low[x], dfn[v]);}if(dfn[x] == low[x]) {tot++;while(1) {int u = sta[top--];belong[u] = tot;size[tot]++;ins[u] = 0;if(u == x) break;}}}inline int topo() {for(int i = 1; i <= tot; i++) for(int j = 1; j <= tot; j++) if(mp[i][j])du[j]++;int h = 0, t = 0, res = 1;for(int i = 1; i <= tot; i++) if(!du[i]) dp[q[t++] = i] = size[i];while(h != t) {int u = q[h++];for(int i = 1; i <= tot; i++) if(mp[u][i] && dp[i] < dp[u] + size[i]) {dp[i] = dp[u] + size[i];q[t++] = i;res = max(res, dp[i]);}}return res;}int main() {n = iread();for(int i = 1; i <= n; i++) head[i] = -1, A[i].read(); cnt = clo = 0;for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) if(i ^ j && bfs(i, j))add(i, j);clo = top = 0;for(int i = 1; i <= n; i++) if(!dfn[i]) tarjan(i);for(int u = 1; u <= n; u++) for(int i = head[u]; ~i; i = g[i].next) if(belong[u] != belong[g[i].v])mp[belong[u]][belong[g[i].v]] = 1;printf("%d\n", topo());return 0;}


0 0
原创粉丝点击