Tomato Automata are small cool programs. You give them an infinite sequence of ones and zeros, and they give you a sequence of numbers. They are widely used in the Stanescu Operating System (SOS). They are written in Tomato Programming Language that is very simple. Here is its specification, tutorial and reference:
Stanescu has lots of Tomato programs. He is interested in maximal length of output sequence that specific program can generate, where the length is the number of printed line numbers. Obviously, it is not possible to test each possible input sequence (of ones and zeros), so he needs a program that computes this.
The input contains several programs, separated with an empty line. Each of them is a correct Tomato program.
For each given program your solution has to print on a separate line the maximal length ofthe output sequence the program could generate. Print `infinity' if there is no maximal length for the 9 output sequence. When finite, the maximal length will not exceed 109 .
Ifgo 2 loop 1 3 die ifgo 2 ifgo 3 pass die pass ifgo 4 jump 5 ifgo 3 loop 2 2 pass loop 1 2 die
7 4
#include#include #include #include #include #include #include using namespace std; #define LL long long const int maxn = 100000+5; const int inf = 1e9; int n , m , ans , size; LL d[maxn] , cnt[maxn] , succ[maxn] , len[maxn]; int dfn , pre[maxn] , low[maxn]; bool sccno[maxn]; stack<int> S; int sign[maxn]; int pos[maxn]; bool inq[maxn] , die[maxn]; char cmd[maxn][82]; char buffer[82]; struct Node { int v , w , pre , t; bool loop; Node *next; }edge[2*maxn] , *first[maxn]; void add(int x,int y,int w,int pre,int t,bool loop) { edge[++m].v = y; edge[m].w = w; edge[m].pre = pre; edge[m].t = t; edge[m].loop = loop; edge[m].next = first[x]; first[x] = &edge[m]; } void init() { m = 0; while (S.size()) S.pop(); memset(pre,0,sizeof(pre)); memset(sccno,false,sizeof(sccno)); dfn = 0; memset(first,0,sizeof(first)); } bool cmd_modify() { bool die = false; for (int i = 0 ; i < n ; ++i) { if (cmd[i][0]=='d') die = true; if (cmd[i][0]=='i' || cmd[i][0]=='j') { int v; sscanf(cmd[i],"%*s%d",&v); --v; if ((i+1)%n==v) cmd[i][0] = 'p'; if (i==v && !die) return false; } } return die; } bool dfs(int u) { pre[u] = low[u] = ++dfn; S.push(u); for (Node * p = first[u] ; p ; p=p->next) { int v = p->v; if (!pre[v]) { if (!dfs(v)) return false; low[u] = min(low[u],low[v]); } else if (!sccno[v]) low[u] = min(low[u],pre[v]); } if (pre[u]==low[u]) { if (u==0 && S.size() > 1) return false; while (true) { int x = S.top() ; S.pop(); sccno[x] = true; if (x==u) break; } } return true; } void BuildGraph() { memset(sign,-1,sizeof(sign)); memset(pos,-1,sizeof(pos)); memset(die,0,sizeof(die)); sign[0] = ++size; pos[size] = 0; int u , v , w , pre , t; for (int i = 0 ; i < n ; ++i) { if (cmd[i][0]=='l') { sscanf(cmd[i],"%*s%d%d",&pre,&t); --pre; if (sign[pre]==-1) { sign[pre] = ++size; pos[size] = pre; } if (sign[i]==-1) { sign[i] = ++size; pos[size] = i; } succ[i] = i; } else if (cmd[i][0]=='i' || cmd[i][0]=='j') { sscanf(cmd[i],"%*s%d",&v); --v; if (cmd[i][0]=='i' && sign[i]==-1) { sign[i] = ++size; pos[size] = i; } succ[i] = v; } else if (cmd[i][0]=='d' ) { if (sign[i]==-1) { sign[i] = ++size; pos[size] = i; } die[sign[i]] = true; succ[i] = i; } else { succ[i] = (i+1)%n; } len[i] = succ[i]==i ? 0 : 1; } for (int i = size ; i >=1 ; --i) { if (die[i]) continue; int u = pos[i] , v , w , pre = -1 , t = -1; v = succ[u] , w = len[u]; memset(inq,false,sizeof(inq)); inq[u] = true; bool lp = false; while (sign[v]==-1) { inq[v] = true; w += len[v]; v = succ[v]; if (inq[v]) { lp = true; break; } } if (lp) { add(sign[u],sign[u],inf,-1,-1,false); continue; } len[u] = w; succ[u] = v; if (v!=u) { add(sign[u],sign[v],w,-1,-1,false); } if (cmd[u][0]=='j') continue; v = (u+1)%n , w = 1; memset(inq,false,sizeof(inq)); lp = false; inq[u] = true; while (sign[v]==-1) { inq[v] = true; w += len[v]; v = succ[v]; if (inq[v]) { lp = true; break; } } if (lp) { add(sign[u],sign[u],inf,-1,-1,false); continue; } if (cmd[u][0]=='l') sscanf(cmd[u],"%*s%d%d",&pre,&t); --pre; add(sign[u],sign[v],w,sign[pre],t,cmd[u][0]=='l'); } } void spfa() { memset(cnt,0,sizeof(cnt)); memset(inq,0,sizeof(inq)); memset(d,0,sizeof(d)); queue<int> q; q.push(sign[0]); ++cnt[sign[0]]; d[sign[0]] = 1; int u , v , w; while (q.size()) { u = q.front(); q.pop(); inq[u] = false; if (die[u] && ans < d[u]) ans = d[u]; for (Node * p = first[u] ; p ; p = p->next) { int v = p->v , w = p->w; if (p->loop) w += (d[u]-d[p->pre]+1)*(p->t-1); if (d[v] < d[u]+w) { d[v] = d[u]+w; if (!inq[v]) { inq[v] = true; q.push(v); ++cnt[v]; if (cnt[v] >= size) { printf("infinity\n"); return; } } } } } cout << ans << endl; } void get_cmd() { for (int i = 0 ; i < strlen(buffer) ; ++i) buffer[i] = tolower(buffer[i]); char * p = strtok(buffer," "); while (p) { strcat(cmd[n],p); strcat(cmd[n]," "); p = strtok(NULL," "); } ++n; } int main() { //freopen("input.in","r",stdin); while (gets(buffer)) { if (buffer[0]==0) break; memset(cmd,0,sizeof(cmd)); n = size = 0; get_cmd(); while (gets(buffer)) { if (buffer[0]==0) break; for (int i = 0 ; i < strlen(buffer) ; ++i) if (isspace(buffer[i])) buffer[i] = ' '; get_cmd(); } if (!cmd_modify()) { printf("infinity\n"); continue; } init(); BuildGraph(); if (!dfs(0)) { printf("infinity\n"); continue; } ans = -1; spfa(); } }