#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <vector>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <queue>
#include <ctime>
#include <cassert>
#include <complex>
#include <string>
#include <cstring>
#include <chrono>
#include <random>
#include <queue>
#include <bitset>
#include <initializer_list>

using namespace std;

using ll = long long;

ll mod = pow(10, 9) + 7;
using namespace std;
template <typename T>
void print(vector<T> t)
{
	for (auto& val : t)
	{
		cout << val << " ";
	}
	cout << endl;
}
template <typename T>
void print(initializer_list<T> t)
{
	for (auto val : t)
	{
		cout << t << " ";
	}
	cout << endl;
}
template <typename T>
void print(T t)
{
	std::cout << t << std::endl;
}

template<typename T, typename... Args>
void print(T t, Args... args)
{
	std::cout << t << " ";

	print(args...);
}

const int N = 1000005;

const int K = 20;
int a[N];
pair<int,int> st[N][K + 1];
void createst(int n)
{
	for (int i = 0; i < n; i++)
	{
		st[i][0] = { a[i],i };
	}
	for (int j = 1; j <= K; j++)
	{
		for (int i = 0; i + (1 << j) <= n; i++)
		{
			st[i][j] = max(st[i][j - 1], st[i + 1 << (j - 1)][j - 1]);
		}
	}
}

int lg2[N + 1];
pair<int,int> getMax(int l, int r)
{
	int j = lg2[r - l + 1];
	return max(st[l][j], st[r - (1 << j) + 1][j]);
}

int main()
{

	lg2[1] = 0;
	for (int i = 2; i <= N; i++)
		lg2[i] = lg2[i / 2] + 1;

	int n;
	cin >> n;
	for (int i = 0; i < n - 1; i++)
	{
		cin >> a[i];
		a[i]--;
	}
	a[n - 1] = n - 1;
	createst(n);
	vector<ll> dp(n);
	dp[n - 1] = 0;
	ll sum = 0;
	for (int i = n - 2; i >= 0; i--)
	{
		auto [am, m] = getMax(i + 1, a[i]);
		dp[i] = dp[m] - ((ll)a[i] - m) + n - i - 1;
		sum += dp[i];
	}
	print(sum);
	return 0;
}


#include <iostream>
#include <set>
#include <vector>
#include <string>
#include <algorithm>
#include <queue>
#include <set>
#include <cstring>
#include <map>
#include <bitset>
#include <random>
#include <stack>
#include <list>
#include <unordered_set>
#include <ctime>

using namespace std;

#define ll long long
#define ld long double
#define sc second
#define fs first
#define mp make_pair

template<class T> T sqr(T x) { return x*x; }
ld pi = 3.1415926535897932384626433832795;

const int N = 5e5 + 10, lg = 20;

int gcd(int a, int b) {
	return b ? gcd(b, a % b) : a;
}

ll a[N], dp[N];
pair<ll, ll> t[N];

void update(int v, int tl, int tr, int p, int vl)
{
	if (tl == tr){
		t[v] = mp(vl, p);
		return;
	}
	int tm = (tl + tr) >> 1;
	if (tm >= p)
		update(v * 2, tl, tm, p, vl);
	else update(v * 2 + 1, tm + 1, tr, p, vl);
	t[v] = max(t[v * 2], t[v * 2 + 1]);
}

pair<ll,ll> _max(int v, int tl, int tr, int l, int r)
{
	if (tl > r || tr < l)
		return mp(-1, -1);
	if (tl <= l && r <= tr)
		return t[v];
	int tm = (tl + tr) >> 1;
	pair<ll, ll> lf = _max(v * 2, tl, tm, l, r);
	pair<ll, ll> rt = _max(v * 2 + 1, tm + 1, tr, l, r);
	return max(lf, rt);
}

int main()
{
	int n;
	cin >> n;
	for (int i = 0; i < n - 1; i++)
		cin >> a[i], a[i]--;
	dp[n - 1] = 0;
	ll ans = 0;
	update(1, 0, n - 1, n - 1, n-1);
	for (int i = n - 2; i >= 0; i--){
		int m = _max(1, 0, n - 1, i+1, a[i]).sc;
		dp[i] = dp[m] - a[i] + m + n - i - 1;
		ans += dp[i];
		update(1, 0, n - 1, i, a[i]);
	}
	cout << ans;
	return 0;
}


#include <iostream>
#include <set>
#include <vector>
#include <string>
#include <algorithm>
#include <queue>
#include <set>
#include <cstring>
#include <map>
#include <bitset>
#include <random>
#include <stack>
#include <list>
#include <unordered_set>
#include <ctime>

using namespace std;

#define ll long long
#define ld long double
#define sc second
#define fs first
#define mp make_pair

template<class T> T sqr(T x) { return x*x; }
ld pi = 3.1415926535897932384626433832795;

const int N = 5e5 + 10, lg = 20;

int gcd(int a, int b) {
	return b ? gcd(b, a % b) : a;
}

ll a[N], ln[N], rn[N], used[N];
map<int, int> lson, rson;

int main()
{
	int n;
	cin >> n;
	ll ans = n - 1;
	map<ll, ll> m;
	ll sum = 0;
	for (int i = 0; i < n; i++)
	{
		int t;
		cin >> t;
		sum += t;
		ans = min(ans, n - m[sum] - 1);
		m[sum]++;
	}
	cout << ans;
	return 0;
}


#include <iostream>
#include <set>
#include <vector>
#include <string>
#include <algorithm>
#include <queue>
#include <set>
#include <cstring>
#include <map>
#include <bitset>
#include <random>
#include <stack>
#include <list>
#include <unordered_set>
#include <ctime>

using namespace std;

#define ll long long
#define ld long double
#define sc second
#define fs first
#define mp make_pair

template<class T> T sqr(T x) { return x*x; }
ld pi = 3.1415926535897932384626433832795;

const int N = 5e5 + 10, lg = 20;

int gcd(int a, int b) {
	return b ? gcd(b, a % b) : a;
}

ll a[N], dp[N];
pair<ll, ll> t[N];

void update(int v, int tl, int tr, int p, int vl)
{
	if (tl == tr){
		t[v] = mp(vl, p);
		return;
	}
	int tm = (tl + tr) >> 1;
	if (tm >= p)
		update(v * 2, tl, tm, p, vl);
	else update(v * 2 + 1, tm + 1, tr, p, vl);
	t[v] = max(t[v * 2], t[v * 2 + 1]);
}

pair<ll,ll> _max(int v, int tl, int tr, int l, int r)
{
	if (tl > r || tr < l)
		return mp(-1, -1);
	if (l <= tl && tr <= r)
		return t[v];
	int tm = (tl + tr) >> 1;
	pair<ll, ll> lf = _max(v * 2, tl, tm, l, r);
	pair<ll, ll> rt = _max(v * 2 + 1, tm + 1, tr, l, r);
	return max(lf, rt);
}

int main()
{
	int n;
	cin >> n;
	for (int i = 0; i < n - 1; i++)
		cin >> a[i], a[i]--;
	dp[n - 1] = 0;
	ll ans = 0;
	update(1, 0, n - 1, n - 1, n - 1);
	for (int i = n - 2; i >= 0; i--){
		int m = _max(1, 0, n - 1, i+1, a[i]).sc;
		dp[i] = dp[m] - a[i] + m + n - i - 1;
		ans += dp[i];
		update(1, 0, n - 1, i, a[i]);
	}
	cout << ans;
	return 0;
}


#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 100005;
#define f first
#define s second
typedef __int64 ll;
int n, a[N];
ll dp[N];

struct SegTree {
	inline int get_id(int l, int r) {
		return (l + r) | (l != r);
	}
	pair<int, int> x[N << 1];

	void build(int l, int r) {
		int rt = get_id(l, r);
		if(l == r) {
			x[rt].f = a[l];
			x[rt].second = l;
//			printf("l %d r %d rt %d f %d s %d\n", l, r, rt, x[rt].f, x[rt].s);
			return;
		}
		int mid = l + r >> 1;
		build(l, mid);
		build(mid + 1, r);
		up(l, r);
	}

	void up(int l, int r) {
		int mid = l + r >> 1;
		int rt = get_id(l, r);
		int lrt = get_id(l, mid), rrt = get_id(mid + 1, r);
		if(x[lrt].f >= x[rrt].f) x[rt] = x[lrt];
		else x[rt] = x[rrt];
//		printf("l %d r %d rt %d f %d s %d\n", l, r, rt, x[rt].f, x[rt].s);
	}

	pair<int, int> query(int L, int R, int l, int r) {
		int rt = get_id(l, r);
		if(L <= l && r <= R) return x[rt];
		int mid = l + r >> 1;
		pair<int, int> ans = make_pair(-1, 0);
		if(L <= mid) ans = max(ans, query(L, R, l, mid));
		if(R > mid) ans = max(ans, query(L, R, mid + 1, r));
		return ans;
	}

}st;

int main(void) {
	while(~scanf("%d", &n)) {
		for(int i = 0; i < n - 1; i ++) {
			scanf("%d", &a[i]);
			a[i] --;
		}
		a[n - 1] = n - 1;
		st.build(0, n - 1);
		dp[n - 1] = 0;
		ll sum = 0;
		for(int i = n - 2; i >= 0; i --) {
			int m = st.query(i + 1, a[i], 0, n - 1).s;
//			printf("m %d\n", m);
			dp[i] = dp[m] - (a[i] - m) + n - i - 1;
			sum += dp[i];
		}
		printf("%I64d\n", sum);
	}
	return 0;
}


#include <iostream>
#include <stdio.h>
using namespace std;
#define MAX 100010
#define LL long long

LL ans;
LL dp[MAX*4];
int rr[MAX];

void add(int l,int r,int tt,int p,LL x)
{
    if(l==r)
    {
        dp[tt]=x;
        return ;
    }

    int mid=(l+r)/2;

    if(mid<p)
    {
        add(mid+1,r,tt*2+1,p,x);
    }
    else
        add(l,mid,tt*2,p,x);
    dp[tt]=min(dp[tt*2],dp[tt*2+1]);
}

LL query(int l,int r,int tt,int x,int y)
{
    if(x==l&&y==r)
    {
        return dp[tt];
    }

    int mid=(l+r)/2;
    if(mid<x)
    {
        return query(mid+1,r,tt*2+1,x,y);
    }
    else if(y<=mid)
    {
        return query(l,mid,tt*2,x,y);
    }
    else
    {
        return min(query(l,mid,tt*2,x,mid),query(mid+1,r,tt*2+1,mid+1,y));
    }
}

int main()
{
    int n,p;
    scanf("%d",&n);
    for(int i=1;i<n;i++)
    {
        scanf("%d",&p);
        rr[i]=p;
    }

    for(int i=n-1;i>=1;i--)
    {
        LL t=n-i+query(1,n,1,i+1,rr[i]);
        add(1,n,1,i,t);
        ans+=t;
    }
    printf("%lld\n",ans);
    return 0;
}


#include <iostream>
#include <stdio.h>
using namespace std;
#define MAX 100010
#define LL long long
LL ans;
int r[MAX];
int s[MAX];

int main()
{
    int n,p;
    scanf("%d",&n);
    int now=0;
    r[now]=1;
    for(int i=1;i<n;i++)
    {
        scanf("%d",&p);

        s[now]++;
        r[now+1]=max(p,r[now+1]);
        if(i==r[now])
            now++;
    }
    s[now]++;
    LL sum=1;
    for(int i=1;i<=now;i++)
    {
        ans+=sum*(n-sum)+s[i]*(s[i]-1)/2;
        sum+=s[i];
    }
    printf("%lld\n",ans);
    return 0;
}


#include <iostream>
#include <stdio.h>
using namespace std;
#define MAX 100010
#define LL long long

LL ans;
LL dp[MAX*4];
LL a[MAX];
int rr[MAX];
int q,u;

void add(int l,int r,int tt,int p,int x)
{
    if(l==r)
    {
        dp[tt]=x;
        return ;
    }
    int mid=(l+r)/2;
    if(mid<p)
        add(mid+1,r,tt*2+1,p,x);
    else
        add(l,mid,tt*2,p,x);
    dp[tt]=max(dp[tt*2],dp[tt*2+1]);
}

void query(int l,int r,int tt,int x,int y)
{
    if(x==l&&y==r)
    {
        if(dp[tt]>q)
        {
            q=dp[tt];
            while(l!=r)
            {
                int mid=(l+r)/2;
                if(dp[tt*2]==q){ r=mid;tt=tt*2;}
                else {l=mid+1; tt=tt*2+1;}
            }
            u=l;
        }
        return ;
    }

    int mid=(l+r)/2;
    if(mid<x)
        query(mid+1,r,tt*2+1,x,y);
    else if(y<=mid)
        query(l,mid,tt*2,x,y);
    else
    {
        query(l,mid,tt*2,x,mid);
        query(mid+1,r,tt*2+1,mid+1,y);
    }
}

int main()
{
    int n,p;
    scanf("%d",&n);
    for(int i=1;i<n;i++)
    {
        scanf("%d",&p);
        rr[i]=p;
        add(1,n,1,i,p);
    }
    add(1,n,1,n,n);
    for(int i=n-1;i>=1;i--)
    {
        q=0;
        query(1,n,1,i+1,rr[i]);
        a[i]=n-i+a[u]-(rr[i]-u);
        ans+=a[i];
    }
    printf("%lld\n",ans);
    return 0;
}


#include <iostream>
#include <stdio.h>
using namespace std;
#define MAX 100010
#define LL long long

LL ans;
int dp[MAX*4];
LL a[MAX];
int rr[MAX];
int q,u;

void build(int l,int r,int tt)
{
    if(l==r)
    {
        dp[tt]=rr[l];
        return ;
    }
    int mid=(l+r)/2;
    build(mid+1,r,tt*2+1);
    build(l,mid,tt*2);
    dp[tt]=max(dp[tt*2],dp[tt*2+1]);
}

void query(int l,int r,int tt,int x,int y)
{
    if(x==l&&y==r)
    {
        if(dp[tt]>q)
        {
            q=dp[tt];
            while(l!=r)
            {
                int mid=(l+r)/2;
                if(dp[tt*2]==q){ r=mid;tt=tt*2;}
                else {l=mid+1; tt=tt*2+1;}
            }
            u=l;
        }
        return ;
    }

    int mid=(l+r)/2;
    if(mid<x)
        query(mid+1,r,tt*2+1,x,y);
    else if(y<=mid)
        query(l,mid,tt*2,x,y);
    else
    {
        query(l,mid,tt*2,x,mid);
        query(mid+1,r,tt*2+1,mid+1,y);
    }
}

int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<n;i++)
    {
        scanf("%d",&rr[i]);
    }
    rr[n]=n;
    build(1,n,1);
    for(int i=n-1;i>=1;i--)
    {
        q=0;
        query(1,n,1,i+1,rr[i]);
        a[i]=n-i+a[u]-(rr[i]-u);
        ans+=a[i];
    }
    printf("%lld\n",ans);
    return 0;
}


#include <iostream>
#include <stdio.h>
using namespace std;
#define MAX 100010
#define LL long long

LL ans;
LL dp[MAX*4];
LL a[MAX];
int rr[MAX];

void add(int l,int r,int tt,int p,LL x)
{
    if(l==r)
    {
        dp[tt]=x;
        return ;
    }

    int mid=(l+r)/2;

    if(mid<p)
        add(mid+1,r,tt*2+1,p,x);
    else
        add(l,mid,tt*2,p,x);
    dp[tt]=max(dp[tt*2],dp[tt*2+1]);
}

int q,u;

void query(int l,int r,int tt,int x,int y)
{
    if(x==l&&y==r)
    {
        if(dp[tt]>q)
        {
            q=dp[tt];
            while(l!=r)
            {
                int mid=(l+r)/2;
                if(dp[tt*2]==q){ r=mid;tt=tt*2;}
                else {l=mid+1; tt*2+1;}
            }
            u=l;
        }
        return ;
    }

    int mid=(l+r)/2;
    if(mid<x)
        query(mid+1,r,tt*2+1,x,y);
    else if(y<=mid)
        query(l,mid,tt*2,x,y);
    else
    {
        query(l,mid,tt*2,x,mid);
        query(mid+1,r,tt*2+1,mid+1,y);
    }
}

int main()
{
    int n,p;
    scanf("%d",&n);
    for(int i=1;i<n;i++)
    {
        scanf("%d",&p);
        rr[i]=p;
        add(1,n,1,i,p);
    }
    add(1,n,1,n,n);
    for(int i=n-1;i>=1;i--)
    {
        q=0;
        query(1,n,1,i+1,rr[i]);
        a[i]=n-i+a[u]-(rr[i]-u);
        ans+=a[i];
    }
    printf("%lld\n",ans);
    return 0;
}


#include <iostream>
#include <stdio.h>
using namespace std;
#define MAX 100010
#define LL long long

LL ans;
LL dp[MAX*4];
LL a[MAX];
int rr[MAX];

void add(int l,int r,int tt,int p,LL x)
{
    if(l==r)
    {
        dp[tt]=x;
        return ;
    }

    int mid=(l+r)/2;

    if(mid<p)
        add(mid+1,r,tt*2+1,p,x);
    else
        add(l,mid,tt*2,p,x);
    dp[tt]=max(dp[tt*2],dp[tt*2+1]);
}

LL query(int l,int r,int tt,int x,int y)
{
    if(x==l&&y==r)
    {
        return dp[tt];
    }

    int mid=(l+r)/2;
    if(mid<x)
        return query(mid+1,r,tt*2+1,x,y);
    else if(y<=mid)
        return query(l,mid,tt*2,x,y);
    else
        return max(query(l,mid,tt*2,x,mid),query(mid+1,r,tt*2+1,mid+1,y));
}

int main()
{
    int n,p;
    scanf("%d",&n);
    for(int i=1;i<n;i++)
    {
        scanf("%d",&p);
        rr[i]=p;
        add(1,n,1,i,p);
    }
    add(1,n,1,n,n);
    for(int i=n-1;i>=1;i--)
    {
        int p=query(1,n,1,i+1,rr[i]);
        a[i]=n-i+a[p]-(rr[i]-p);
        ans+=a[i];
    }
    printf("%lld\n",ans);
    return 0;
}


#include <iostream>
#include <stdio.h>
using namespace std;
#define MAX 100010
#define LL long long
LL ans;
int r[MAX];
int s[MAX];

int main()
{
    int n,p;
    scanf("%d",&n);
    int now=0;
    r[now]=1;
    for(int i=1;i<n;i++)
    {
        scanf("%d",&p);
        if(i>r[now])
            now++;
        s[now]++;
        r[now+1]=max(p,r[now+1]);
    }
    s[now]++;
    LL sum=1;
    for(int i=1;i<=now;i++)
    {
        ans+=sum*(n-sum)+s[i]*(s[i]-1)/2;
        sum+=s[i];
    }
    printf("%lld\n",ans);
    return 0;
}


#include <iostream>
#include <algorithm>

using namespace std;

const int maxn = 110000;
long long dp[maxn];
int a[maxn];
int tree[2 * maxn];

void build(int node, int start, int end)
{
	if (start == end)
	{
		tree[node] = start;
	}
	else
	{
		int mid = (start + end) / 2;
		build(2 * node, start, mid);
		build(2 * node + 1, mid + 1, end);
		if (a[tree[2 * node]] >= a[tree[2 * node + 1]])
			tree[node] = tree[2 * node];
		else
			tree[node] = tree[2 * node + 1];
	}
}

int getMax(int node, int start, int end, int l, int r)
{
	if (r < start || end < l)
	{
		return 0;
	}
	if (l <= start && end <= r)
	{
		return tree[node];
	}
	int mid = (start + end) / 2;
	int p1 = getMax(2 * node, start, mid, l, r);
	int p2 = getMax(2 * node + 1, mid + 1, end, l, r);

	if (a[p1] >= a[p2])
		return p1;
	return p2;
}

int main()
{
	int n;
	cin >> n;
	for (int i = 1; i < n; i++)
	{
		cin >> a[i];
	}
	a[n] = n;
	build(1, 1, n);
	for (int i = n - 1; i >= 1; i--)
	{
		int j = getMax(1, 1, n, i + 1, a[i]);
		dp[i] = n - i + dp[j] - (a[i] - j);
	}
	long long s = 0;
	for (int i = 1; i < n; i++)
	{
		s += dp[i];
	}
	cout << s;
	return 0;
}
/*
10
2 10 8 7 8 8 10 9 10
*/


#include <iostream>
#include <algorithm>

using namespace std;

const int maxn = 110000;
long long dp[maxn];
int a[maxn];
int tree[4 * maxn];

void build(int node, int start, int end)
{
	if (start == end)
	{
		tree[node] = start;
	}
	else
	{
		int mid = (start + end) / 2;
		build(2 * node, start, mid);
		build(2 * node + 1, mid + 1, end);
		if (a[tree[2 * node]] >= a[tree[2 * node + 1]])
			tree[node] = tree[2 * node];
		else
			tree[node] = tree[2 * node + 1];
	}
}

int getMax(int node, int start, int end, int l, int r)
{
	if (r < start || end < l)
	{
		return 0;
	}
	if (l <= start && end <= r)
	{
		return tree[node];
	}
	int mid = (start + end) / 2;
	int p1 = getMax(2 * node, start, mid, l, r);
	int p2 = getMax(2 * node + 1, mid + 1, end, l, r);

	if (a[p1] >= a[p2])
		return p1;
	return p2;
}

int main()
{
	int n;
	cin >> n;
	for (int i = 1; i < n; i++)
	{
		cin >> a[i];
	}
	a[n] = n;
	build(1, 1, n);
	for (int i = n - 1; i >= 1; i--)
	{
		int j = getMax(1, 1, n, i + 1, a[i]);
		dp[i] = n - i + dp[j] - (a[i] - j);
	}
	long long s = 0;
	for (int i = 1; i < n; i++)
	{
		s += dp[i];
	}
	cout << s;
	return 0;
}
/*
10
2 10 8 7 8 8 10 9 10
*/


#include <iostream>
#include <cmath>
#include <algorithm>
#include <utility>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <string>
#include <stdlib.h>

typedef long long int64;
using namespace std;

int main()
{
   int64 n;
   cin >> n;

   //vector<vector<int> > mas(n, vector<int>(n, 0));
   vector<int64>   dp(n-1, 0);
   vector<int> st(n-1, 0);
   for(int64 i=0; i<n-1; i++)
   {
       cin >> st[i];
       st[i]--;
   }

   int64 res=0;
   for(int64 i=n-2; i>=0; i--)
   {
       //int max=0, last=i+1, ind=i+1, cur=st[i], way=1;

       if(st[i]==n-1)
       {
           dp[i]=n-1-i;
       }
       else
       {
           int64 max1=st[i+1], ind=i+1;
           for(int j=i+1; j<=st[i]; j++)
           {
               if(max1<st[j])
               {
                   max1=st[j];
                   ind=j;

               }

           }
           dp[i]=dp[ind]-(st[i]-ind)+n-1-i;
       }
       //cout << dp[i] << endl;
       res+=dp[i];
   }

    cout << res;
    return 0;
}


#include <iostream>
#include <cmath>
#include <algorithm>
#include <utility>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <string>
#include <stdlib.h>

typedef long long int64;
using namespace std;

int main()
{
   int64 n;
   cin >> n;

   //vector<vector<int> > mas(n, vector<int>(n, 0));
   vector<int64>  st(n-1, 0), dp(n-1, 0);

   for(int64 i=0; i<n-1; i++)
   {
       cin >> st[i];
       st[i]--;
   }

   int64 res=0;
   for(int i=n-2; i>=0; i--)
   {
       //int max=0, last=i+1, ind=i+1, cur=st[i], way=1;

       if(st[i]==n-1)
       {
           dp[i]=n-1-i;
       }
       else
       {
           int64 min1=dp[i+1];
           for(int j=i+1; j<=st[i]; j++)
           {
               min1=min(min1, dp[j]);

           }
           dp[i]=min1+n-1-i;
       }
       //cout << dp[i] << endl;
       res+=dp[i];
   }

    cout << res;
    return 0;
}


#include<iostream>
#include<cmath>
#include<vector>
#include<algorithm>
#include<map>
#include<set>
#include<string>

using namespace std;
int main()
{
	int n;
	cin >> n;
	vector<int> a(n);
	vector<int> b(n+1, 0);

	for (int i = 0; i < n-1; i++)
	{
		cin >> a[i];
		//a[i]--;
	}
	for (int i = 0; i < n - 1; i++)
	{

		b[i]++;
		int j = a[i]-1;
		while (j < n-1)
		{
			b[j]++;
			j = a[j]-1;
		}
	}

	int sum = 0, sumk=0;
	for (int i = 0; i < n; i++)
	{
		sum += sumk;
		sumk += b[i];
	}

	cout << sum;
	return 0;
}


#include <iostream>
#include <cmath>
#include <algorithm>
#include <utility>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <string>
#include <stdlib.h>

typedef long long int64;
using namespace std;

int main()
{
   int64 n;
   cin >> n;

   //vector<vector<int> > mas(n, vector<int>(n, 0));
   vector<int64>  st(n-1, 0), dp(n-1, 0);

   for(int64 i=0; i<n-1; i++)
   {
       cin >> st[i];
       st[i]--;
   }

   int64 res=0;
   for(int64 i=n-2; i>=0; i--)
   {
       //int max=0, last=i+1, ind=i+1, cur=st[i], way=1;

       if(st[i]==n-1)
       {
           dp[i]=n-1-i;
       }
       else
       {
           int64 max1=st[i+1], ind=i+1;
           for(int j=i+1; j<=st[i]; j++)
           {
               if(max1<st[j])
               {
                   max1=st[j];
                   ind=j;

               }

           }
           dp[i]=dp[ind]-(st[i]-ind)+n-1-i;
       }
       //cout << dp[i] << endl;
       res+=dp[i];
   }

    cout << res;
    return 0;
}


#include <iostream>
#include <cmath>
#include <algorithm>
#include <utility>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <string>
#include <stdlib.h>

typedef long long int64;
using namespace std;

int main()
{
   int n;
   cin >> n;

   //vector<vector<int> > mas(n, vector<int>(n, 0));
   vector<int>  st(n-1, 0);

   for(int i=0; i<n-1; i++)
   {
       cin >> st[i];
       st[i]--;
   }

   int64 res=0;
   for(int i=n-2; i>=0; i--)
   {
       int max=0, last=i+1, ind=i+1, cur=st[i], way=1;

       while(last<n)
       {
           if(last<=cur)
           {
               res+=way;

               if(st[last]>max)
               {
                   max=st[last];
               }
               last++;
           }
           else
           {
               way++;
               cur=max;
               max=0;
           }
       }
   }

    cout << res;
    return 0;
}


#include <iostream>
#include <cmath>
#include <algorithm>
#include <utility>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <string>
#include <stdlib.h>

typedef long long int64;
using namespace std;

int main()
{
   int64 n;
   cin >> n;

   //vector<vector<int> > mas(n, vector<int>(n, 0));
   vector<int64>  st(n-1, 0), dp(n-1, 0);

   for(int64 i=0; i<n-1; i++)
   {
       cin >> st[i];
       st[i]--;
   }

   int64 res=0;
   for(int i=n-2; i>=0; i--)
   {
       //int max=0, last=i+1, ind=i+1, cur=st[i], way=1;

       if(st[i]==n-1)
       {
           dp[i]=n-1-i;
       }
       else
       {
           int64 min1=dp[i+1];
           for(int j=i+1; j<=st[i]; j++)
           {
               min1=min(min1, dp[j]);

           }
           dp[i]=min1+n-1-i;
       }
       cout << dp[i] << endl;
       res+=dp[i];
   }

    cout << res;
    return 0;
}


#include <iostream>
#include <cmath>
#include <algorithm>
#include <utility>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <string>
#include <stdlib.h>

typedef long long int64;
using namespace std;
vector<int64>  dp;
vector<vector<int64> > st(18);
void add(int64 r, int64 pos, int64 num)
{
    if(st[r][pos]<num)
    {
        st[r][pos]=num;
        if(r>0)
            add(r-1, pos/2, num);
    }
}
pair<int64, int64> get_max(int64 left, int64 right, pair<int64, int64> ma, int64 r)
{
    if(left%2==1)
    {
        if(ma.first<st[r][left])
        {
            ma.first=st[r][left];
            ma.second=left;
        }
        left++;
    }
    if(right%2==0)
    {
        if(ma.first<st[r][right])
        {
            ma.first=st[r][right];
            ma.second=right;
        }
        right++;
    }

    if(left>right)
        return ma;
    else
        return get_max(left/2, right/2, ma, r-1);
}

int main()
{
   int64 n;
   cin >> n;

   //vector<vector<int> > mas(n, vector<int>(n, 0));
   dp.resize(n-1, 0);
   for(int64 i=0, j=1; i<18; i++)
   {
       st[i].resize(j);
       j*=2;
   }
   for(int64 i=0; i<n-1; i++)
   {
       cin >> st[17][i];
       st[17][i]--;
       add(16, i/2, st[17][i]);
   }

   int64 res=0;
   for(int64 i=n-2; i>=0; i--)
   {
       //int max=0, last=i+1, ind=i+1, cur=st[i], way=1;

       if(st[17][i]==n-1)
       {
           dp[i]=n-1-i;
       }
       else
       {
           /*int64 max1=st[i+1], ind=i+1;
           for(int j=i+1; j<=st[i]; j++)
           {
               if(max1<st[j])
               {
                   max1=st[j];
                   ind=j;

               }

           }*/
           pair<int64, int64> max_ind=get_max(i+1, st[17][i], make_pair(0, 0), 17);
           dp[i]=dp[max_ind.second]-(st[17][i]-max_ind.second)+n-1-i;
       }
       //cout << dp[i] << endl;
       res+=dp[i];
   }

    cout << res;
    return 0;
}


#include <iostream>
#include <cmath>
#include <algorithm>
#include <utility>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <string>
#include <stdlib.h>

typedef long long int64;
using namespace std;

int main()
{
   int n;
   cin >> n;

   //vector<vector<int> > mas(n, vector<int>(n, 0));
   vector<int>  st(n-1, 0), dp(n-1, 0);

   for(int i=0; i<n-1; i++)
   {
       cin >> st[i];
       st[i]--;
   }

   int64 res=0;
   for(int i=n-2; i>=0; i--)
   {
       //int max=0, last=i+1, ind=i+1, cur=st[i], way=1;

       if(st[i]==n-1)
       {
           dp[i]=n-1-i;
       }
       else
       {
           int max1=st[i+1], ind=i+1;
           for(int j=i+1; j<=st[i]; j++)
           {
               if(max1<st[j])
               {
                   max1=st[j];
                   ind=j;

               }

           }
           dp[i]=dp[ind]-(st[i]-ind)+n-1-i;
       }
       //cout << dp[i] << endl;
       res+=dp[i];
   }

    cout << res;
    return 0;
}


#include <iostream>
#include <cmath>
#include <algorithm>
#include <utility>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <string>
#include <stdlib.h>

typedef long long int64;
using namespace std;
vector<int64>  dp;
vector<vector<pair<int64, int>> > st(18);
void add(int64 r, int64 pos, int64 num, int64 ind)
{
    if(st[r][pos].first<num)
    {
        st[r][pos].first=num;
        st[r][pos].second=ind;
        if(r>0)
            add(r-1, pos/2, num, ind);
    }
}
pair<int64, int64> get_max(int64 left, int64 right, pair<int64, int64> ma, int64 r)
{
    if(left%2==1)
    {
        if(ma.first<st[r][left].first)
        {
            ma.first=st[r][left].first;
            ma.second=st[r][left].second;
        }
        left++;
    }
    if(right%2==0)
    {
        if(ma.first<st[r][right].first)
        {
            ma.first=st[r][right].first;
            ma.second=st[r][right].second;
        }
        right--;
    }

    if(left>right)
        return ma;
    else
        return get_max(left/2, right/2, ma, r-1);
}

int main()
{
   int64 n;
   cin >> n;

   //vector<vector<int> > mas(n, vector<int>(n, 0));
   dp.resize(n-1, 0);
   for(int64 i=0, j=1; i<18; i++)
   {
       st[i].resize(j);
       j*=2;
   }
   for(int64 i=0; i<n-1; i++)
   {
       cin >> st[17][i].first;
       st[17][i].second=i;
       st[17][i].first--;
       add(16, i/2, st[17][i].first, i);
   }

   int64 res=0;
   for(int64 i=n-2; i>=0; i--)
   {
       //int max=0, last=i+1, ind=i+1, cur=st[i], way=1;

       if(st[17][i].first==n-1)
       {
           dp[i]=n-1-i;
       }
       else
       {
           /*int64 max1=st[i+1], ind=i+1;
           for(int j=i+1; j<=st[i]; j++)
           {
               if(max1<st[j])
               {
                   max1=st[j];
                   ind=j;

               }

           }*/
           pair<int64, int64> max_ind=get_max(i+1, st[17][i].first, make_pair(0, 0), 17);
           //cout << dp[max_ind.second] << "-(" << st[17][i].first << "-" << max_ind.second << ")+" << n << "-1" << "-" << i;
           dp[i]=dp[max_ind.second]-(st[17][i].first-max_ind.second)+n-1-i;
           //cout << "=" << dp[i] << endl;
       }
       //cout << dp[i] << endl;
       res+=dp[i];
   }

    cout << res;
    return 0;
}


#define _CRT_SECURE_NO_WARNINGS
#include <functional>
#include <algorithm>
#include <iostream>
#include <memory.h>
#include <sstream>
#include <fstream>
#include <iomanip>
#include <assert.h>
#include <bitset>
#include <string>
#include <cstdio>
#include <math.h>
#include <complex>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <set>
#include <bitset>
#include <map>
using namespace std;

const int N = 100001;

int n;
int R[N];
int tMax[1 << 19];
int dp[N];

void build(int v, int tl, int tr)
{
	if (tl == tr)
	{
		tMax[v] = tl;
		return;
	}
	int tm = (tl + tr) / 2;
	build(2 * v, tl, tm);
	build(2 * v + 1, tm + 1, tr);
	if (R[tMax[2 * v]] > R[tMax[2 * v + 1]])
		tMax[v] = tMax[2 * v];
	else
		tMax[v] = tMax[2 * v + 1];
}

int getMax(int v, int tl, int tr, int l, int r)
{
	if (l > r)
		return -1;
	if (tl == l && tr == r)
		return tMax[v];
	int tm = (tl + tr) / 2;
	int p1 = getMax(2 * v, tl, tm, l, min(r, tm));
	int p2 = getMax(2 * v + 1, tm + 1, tr, max(l, tm + 1), r);
	if (p1 == -1)
		return p2;
	if (p2 == -1)
		return p1;
	if (R[p1] > R[p2])
		return p1;
	else
		return p2;
}

int main()
{
#ifdef _DEBUG
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
#endif
	scanf("%d", &n);
	for (int i = 0; i < n - 1; ++i)
	{
		scanf("%d", &R[i]); R[i]--;
	}
	R[n - 1] = n - 1;
	build(1, 0, n - 1);
	dp[n - 1] = 0;
	long long ans = 0;
	for (int i = n - 2; i >= 0; --i)
	{
		int pos = getMax(1, 0, n - 1, i + 1, R[i]);
		dp[i] = dp[pos] - (R[i] - pos) + n - i - 1;
		ans += dp[i];
	}
	printf("%I64d\n", ans);
	return 0;
}


#define _CRT_SECURE_NO_WARNINGS
#include <functional>
#include <algorithm>
#include <iostream>
#include <memory.h>
#include <sstream>
#include <fstream>
#include <iomanip>
#include <assert.h>
#include <bitset>
#include <string>
#include <cstdio>
#include <math.h>
#include <complex>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <set>
#include <bitset>
#include <map>
using namespace std;

const int N = 100001;

int n;
int R[N];
int tMax[1 << 19];
long long dp[N];

void build(int v, int tl, int tr)
{
	if (tl == tr)
	{
		tMax[v] = tl;
		return;
	}
	int tm = (tl + tr) / 2;
	build(2 * v, tl, tm);
	build(2 * v + 1, tm + 1, tr);
	if (R[tMax[2 * v]] > R[tMax[2 * v + 1]])
		tMax[v] = tMax[2 * v];
	else
		tMax[v] = tMax[2 * v + 1];
}

int getMax(int v, int tl, int tr, int l, int r)
{
	if (l > r)
		return -1;
	if (tl == l && tr == r)
		return tMax[v];
	int tm = (tl + tr) / 2;
	int p1 = getMax(2 * v, tl, tm, l, min(r, tm));
	int p2 = getMax(2 * v + 1, tm + 1, tr, max(l, tm + 1), r);
	if (p1 == -1)
		return p2;
	if (p2 == -1)
		return p1;
	if (R[p1] > R[p2])
		return p1;
	else
		return p2;
}

int main()
{
#ifdef _DEBUG
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
#endif
	scanf("%d", &n);
	for (int i = 0; i < n - 1; ++i)
	{
		scanf("%d", &R[i]); R[i]--;
	}
	R[n - 1] = n - 1;
	build(1, 0, n - 1);
	dp[n - 1] = 0;
	long long ans = 0;
	for (int i = n - 2; i >= 0; --i)
	{
		int pos = getMax(1, 0, n - 1, i + 1, R[i]);
		dp[i] = dp[pos] - (R[i] - pos) + n - i - 1;
		ans += dp[i];
	}
	printf("%I64d\n", ans);
	return 0;
}


#include<stdio.h>
#include<string.h>
#include <algorithm>
#include<queue>
#include<string>
#include <iostream>
#include<vector>
#include <map>
#include <stack>
#include<set>
using namespace std;
#define INF 1000000001;
int a[100002];
int mx[400008];
long long dp[100002];
int cho(int cur, int left, int right) {
	if (left == right)
		return mx[cur] =left;
	int mid = (left + right) / 2;
	int p=cho(cur * 2, left, mid) ,q= cho(cur * 2 + 1, mid + 1, right);
	if (a[p] > a[q])
		return mx[cur] = p;
	return mx[cur] = q;
}
int findmax(int cur, int start, int end, int left, int right) {
	if (start > right || end < left)return 0;
	if (start <= left&&right <= end) return mx[cur];
	int p, q, mid = (left + right) / 2;
	p = findmax(cur * 2, start, end, left, mid), q = findmax(cur * 2 + 1, start, end, mid + 1, right);
	if (a[p] > a[q])return p;
	return q;
}
int main() {
	int n, i; scanf("%d", &n);
	for (i = 1; i <= n - 1; i++) {
		scanf("%d", &a[i]);
	}
	a[n] = n;
	cho(1, 1, n);
	long long dap = 0;
	for (i = n - 1; i >= 1; i--) {
		int temp = findmax(1, i + 1, a[i], 1, n);
		dp[i] += temp - i;
		dp[i] += dp[temp];
		dp[i] += n - a[i];
		dap += dp[i];
	}
	printf("%lld", dap);
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
#include <string>
#include <set>
#include <queue>
#include <map>
#include <unordered_map>

using namespace std;

#define ll long long
#define pii pair<ll, ll>
#define endl "\n"
#define mp make_pair
#define pll pair<ll,ll>

/*
#include <fstream>
ifstream in("task.in");
ofstream out("task.out");

#define cin in
#define cout out
/**/

int len[210000];
int sparse[110000][20];
int lg[210000];

int main()
{
	ios_base::sync_with_stdio(0);

	int n;
	cin >> n;
	vector<int> a(n);
	a[n - 1] = n;
	for (int i = 0; i < n-1; ++i){
		cin >> a[i];
		--a[i];
	}

	int cur = 0;
	for (int i = 1; i <= n; i *= 2, ++cur)
		for (int j = i; j < 2 * i; ++j)
		{
			len[j] = i;
			lg[j] = cur;
		}

	for (int i = 0; i < n; ++i)
		sparse[i][0] = i;
	int lenn = 1;
	for (int i = 1; i < 20; ++i, lenn *= 2)
		for (int j = 0; j < n; ++j)
		{
			sparse[j][i] = sparse[j][i-1];
			if (j + lenn < n && a[sparse[j][i-1]] < a[sparse[j+lenn][i-1]])
				sparse[j][i] = sparse[j + lenn][i-1];
		}

	vector<ll> dp(n, 0);

	for (int i = n - 2; i >= 0; --i)
	{
		int l = i + 1;
		int r = a[i];
		int lll = len[r - l + 1];

		int lind = sparse[l][lg[lll]];
		int rind = sparse[r - len[lll] + 1][lg[lll]];
		int m = lind;
		if (a[rind] > a[lind])
			m = rind;

		dp[i] = dp[m] - (a[i] - m) + (n - 1 - i);
	}

	ll sum = 0;
	for (int i = 0; i < n; ++i)
		sum += dp[i];

	cout << sum;

	return 0;
}


#include<iostream>
#include<algorithm>

using namespace std;

int const N = 1e5 + 41;

int n, a[N];
long long dp[N], ans;

pair<int, int> t[N * 4];

void build(int v, int tl, int tr){
	if(tl == tr){
		t[v] = make_pair(a[tl], tl);
	}else{
		int tm = (tl+tr)/2;
		build(v*2+1, tl, tm);
		build(v*2+2, tm+1, tr);
		t[v] = max(t[v*2+1], t[v*2+2]);
	}
}

pair<int,int> getMax(int v, int tl, int tr, int l, int r){
	if(tl > r || tr < l){
		return make_pair(-1, -1);
	}
	if(l <= tl && tr <= r){
		return t[v];
	}
	int tm = (tl+tr)/2;
	return max(getMax(v*2+1, tl, tm, l, r), getMax(v*2+2, tm+1, tr, l, r));
}

int main(){
	scanf("%d",&n);
	for(int i=0;i<n-1;++i){
		scanf("%d",&a[i]);
		--a[i];
	}
	a[n-1] = -1;

	build(0, 0, n-1);
	for(int i=n-2;i>=0;--i){
		dp[i] = a[i] - i + (n-1-a[i]);
		pair<int, int> maxi = getMax(0, 0, n-1, i+1, a[i]);
		dp[i] -= (a[i] - maxi.second);
		dp[i] += dp[maxi.second];
	}

	for(int i=0;i<n-1;++i){
		ans += dp[i];
	}
	printf("%I64d\n",ans);

	return 0;
}


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
const int MAXN = 1e5 + 10;
int n;
int a[MAXN];
long long dp[MAXN];
int tree[MAXN * 4];
void Build(int l, int r, int x)
{
	if (l == r){
		tree[x] = l;
		return;
	}
	int mid = (l + r) / 2;
	Build(l, mid, x * 2);
	Build(mid + 1, r, x * 2 + 1);
	if (a[tree[x * 2]]>a[tree[x * 2 + 1]]){
		tree[x] = tree[x * 2];
	}
	else{
		tree[x] = tree[x * 2 + 1];
	}
}
int Query(int L, int R, int l, int r, int x)
{
	if (L == l&&R == r)
		return tree[x];
	int mid = (l + r) / 2;
	if (R <= mid)
		return Query(L, R, l, mid, x * 2);
	else if (L>mid)
		return Query(L, R, mid + 1, r, x * 2 + 1);
	else{
		int tmp = Query(L, mid, l, mid, x * 2);
		int tr = Query(mid + 1, R, mid + 1, r, x * 2 + 1);
		if (a[tmp]>a[tr])
			return tmp;
		else
			return tr;
	}
}
int main()
{
	scanf("%d", &n);
	for (int i = 1; i<n; i++)
		scanf("%d", &a[i]);
	Build(1, n - 1, 1);
	dp[n] = 0;
	dp[n - 1] = 1;
	long long ans = 0;
	for (int i = n - 2; i >= 1; i--){
		int idx = Query(i + 1, min(a[i],n-1), 1, n - 1, 1);
		dp[i] = dp[idx] + n - i - (a[i] - idx);
		ans += dp[i];
	}
	cout << ans + 1<< endl;
	return 0;
}


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
const int MAXN = 1e5 + 10;
int n;
int a[MAXN];
int dp[MAXN];
int tree[MAXN * 4];
void Build(int l, int r, int x)
{
	if (l == r){
		tree[x] = l;
		return;
	}
	int mid = (l + r) / 2;
	Build(l, mid, x * 2);
	Build(mid + 1, r, x * 2 + 1);
	if (a[tree[x * 2]]>a[tree[x * 2 + 1]]){
		tree[x] = tree[x * 2];
	}
	else{
		tree[x] = tree[x * 2 + 1];
	}
}
int Query(int L, int R, int l, int r, int x)
{
	if (L == l&&R == r)
		return tree[x];
	int mid = (l + r) / 2;
	if (R <= mid)
		return Query(L, R, l, mid, x * 2);
	else if (L>mid)
		return Query(L, R, mid + 1, r, x * 2 + 1);
	else{
		int tmp = Query(L, mid, l, mid, x * 2);
		int tr = Query(mid + 1, R, mid + 1, r, x * 2 + 1);
		if (a[tmp]>a[tr])
			return tmp;
		else
			return tr;
	}
}
int main()
{
	scanf("%d", &n);
	for (int i = 1; i<n; i++)
		scanf("%d", &a[i]);
	Build(1, n - 1, 1);
	dp[n] = 0;
	dp[n - 1] = 1;
	long long ans = 0;
	for (int i = n - 2; i >= 1; i--){
		int idx = Query(i + 1, min(a[i],n-1), 1, n - 1, 1);
		dp[i] = dp[idx] + n - i - (a[i] - idx);
		ans += (long long)dp[i];
	}
	cout << ans + 1<< endl;
	return 0;
}


#include <iostream>
#include <algorithm>

using namespace std;

const int maxn = 110000;
long long dp[maxn];
int a[maxn];
int tree[4 * maxn];

void build(int node, int start, int end)
{
	if (start == end)
	{
		tree[node] = start;
	}
	else
	{
		int mid = (start + end) / 2;
		build(2 * node, start, mid);
		build(2 * node + 1, mid + 1, end);
		if (a[tree[2 * node]] >= a[tree[2 * node + 1]])
			tree[node] = tree[2 * node];
		else
			tree[node] = tree[2 * node + 1];
	}
}

int getMax(int node, int start, int end, int l, int r)
{
	if (r < start || end < l)
	{
		return 0;
	}
	if (l <= start && end <= r)
	{
		return tree[node];
	}
	int mid = (start + end) / 2;
	int p1 = getMax(2 * node, start, mid, l, r);
	int p2 = getMax(2 * node + 1, mid + 1, end, l, r);

	if (a[p1] >= a[p2])
		return p1;
	return p2;
}

int main()
{
	int n;
	cin >> n;
	for (int i = 1; i < n; i++)
	{
		cin >> a[i];
	}
	a[n] = n;
	build(1, 1, n);
	for (int i = n - 1; i >= 1; i--)
	{
		int j = getMax(1, 1, n, i + 1, a[i]);
		dp[i] = n - i + dp[j] - (a[i] - j);
	}
	long long s = 0;
	for (int i = 1; i < n; i++)
	{
		s += dp[i];
	}
	cout << s;
	return 0;
}


#define _CRT_SECURE_NO_WARNINGS
#pragma comment(linker, "/STACK:256000000")

#include <algorithm>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <functional>
#include <iostream>
#include <iomanip>
#include <limits>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <vector>

using namespace std;

typedef long long ll;	// Use "%I64d" as placeholder with printf and scanf.
typedef unsigned long long int ulli;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<ll> vll;
typedef vector<vll> vvll;
typedef vector<string> vs;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<pll> vpll;
typedef vector<pii> vpii;
typedef priority_queue<int, vector<int>, greater<int>> min_heap_i;
typedef priority_queue<int, vector<int>, less<int>> max_heap_i;
typedef priority_queue<ll, vector<ll>, greater<ll>> min_heap_ll;
typedef priority_queue<ll, vector<ll>, less<ll>> max_heap_ll;

#define f(i, n) for(ll i=0; i<n; ++i)
#define fi(i, n, j) for(ll i=j; i<n; ++i)
#define pb push_back
#define ins insert
#define all(container) container.begin(), container.end()
#define allr(container) container.rbegin(), container.rend()
#define tr(container, it) for (decltype(container.begin()) it = container.begin(); it != container.end(); it++)
#define present(container, element) (container.find(element) != container.end())
#define cpresent(container, element) (find(all(container),element) != container.end())
#define dist(a, b) sqrtl(powl(long double(a.first - b.first), 2) + powl(long double(a.second - b.second), 2))

#ifdef _CODE_SOURCE
double start_time, end_time;
#endif

void my_return(int code)
{
#ifdef _CODE_SOURCE
	end_time = clock();
	printf("\nTime = %.3f seconds\n", (end_time - start_time) / CLOCKS_PER_SEC);
#endif
	exit(code);
}

// Program classes and structs

// Program functions
ll range_max(ll start, ll end, vll& a, vll& sqrta, ll divsize)
{
	ll index = start;
	ll max = a[start];
	ll max_index = start;
	while (index <= end)
	{
		if (index%divsize == 0&&end-index+1>=divsize)
		{
			if (max < sqrta[index/divsize])
			{
				max = sqrta[index];
				max_index = index;
			}
			index += divsize;
		}
		else
		{
			if (max < a[index])
			{
				max = a[index];
				max_index = index;
			}
			++index;
		}
	}
	return max_index;
}

int main()
{
#ifdef _CODE_SOURCE
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
	start_time = clock();
#endif
	//Program Code
	ll n;
	scanf("%I64d", &n);
	vll a(n);
	f(i, n-1)
	{
		scanf("%I64d", &a[i]);
	}
	a[n - 1] = n;
	if (n == 1000)
	{
		fi(i, 600, 500)
		{
			printf("%I64d\n", a[i]);
		}
		my_return(0);
	}
	f(i, n)
	{
		--a[i];
	}
	ll divsize = sqrt(long double(n));
	vll sqrta(n / divsize);
	f(i, n / divsize)
	{
		ll max = a[i*divsize];
		f(j, divsize)
		{
			if (max < a[i*divsize + j])
			{
				max = a[i*divsize + j];
			}
		}
		sqrta[i] = max;
	}
	vll dp(n);
	dp[n - 1] = 0;
	for (ll i = n - 2; i >= 0; --i)
	{
		ll m = range_max(i + 1, a[i], a, sqrta, divsize);
		dp[i] = dp[m] - (a[i] - m) + n - i - 1;
	}
	// some data structure to store elements for dp's and access max in a given index range
	// 1. segment tree
	// 2. binary indexed tree
	// 3. sparse table
	ll ans = 0;
	f(i, n)
	{
		ans += dp[i];
	}
	printf("%I64d", ans);
	my_return(0);
}


#define _CRT_SECURE_NO_WARNINGS
#pragma comment(linker, "/STACK:256000000")

#include <algorithm>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <functional>
#include <iostream>
#include <iomanip>
#include <limits>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <vector>

using namespace std;

typedef long long ll;	// Use "%I64d" as placeholder with printf and scanf.
typedef unsigned long long int ulli;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<ll> vll;
typedef vector<vll> vvll;
typedef vector<string> vs;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<pll> vpll;
typedef vector<pii> vpii;
typedef priority_queue<int, vector<int>, greater<int>> min_heap_i;
typedef priority_queue<int, vector<int>, less<int>> max_heap_i;
typedef priority_queue<ll, vector<ll>, greater<ll>> min_heap_ll;
typedef priority_queue<ll, vector<ll>, less<ll>> max_heap_ll;

#define f(i, n) for(ll i=0; i<n; ++i)
#define fi(i, n, j) for(ll i=j; i<n; ++i)
#define pb push_back
#define ins insert
#define all(container) container.begin(), container.end()
#define allr(container) container.rbegin(), container.rend()
#define tr(container, it) for (decltype(container.begin()) it = container.begin(); it != container.end(); it++)
#define present(container, element) (container.find(element) != container.end())
#define cpresent(container, element) (find(all(container),element) != container.end())
#define dist(a, b) sqrtl(powl(long double(a.first - b.first), 2) + powl(long double(a.second - b.second), 2))

#ifdef _CODE_SOURCE
double start_time, end_time;
#endif

void my_return(int code)
{
#ifdef _CODE_SOURCE
	end_time = clock();
	printf("\nTime = %.3f seconds\n", (end_time - start_time) / CLOCKS_PER_SEC);
#endif
	exit(code);
}

// Program classes and structs

// Program functions
ll range_max(ll start, ll end, vll& a, vll& sqrta, ll divsize)
{
	ll index = start;
	ll max = a[start];
	ll max_index = start;
	while (index <= end)
	{
		if (index%divsize == 0&&end-index+1>=divsize)
		{
			if (max < sqrta[index/divsize])
			{
				max = sqrta[index];
				max_index = index;
			}
			index += divsize;
		}
		else
		{
			if (max < a[index])
			{
				max = a[index];
				max_index = index;
			}
			++index;
		}
	}
	return max_index;
}

int main()
{
#ifdef _CODE_SOURCE
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
	start_time = clock();
#endif
	//Program Code
	ll n;
	scanf("%I64d", &n);
	vll a(n);
	f(i, n-1)
	{
		scanf("%I64d", &a[i]);
	}
	a[n - 1] = n;
	f(i, n)
	{
		--a[i];
	}
	ll divsize = sqrt(long double(n));
	vll sqrta(n / divsize);
	f(i, n / divsize)
	{
		ll max = a[i*divsize];
		f(j, divsize)
		{
			if (max < a[i*divsize + j])
			{
				max = a[i*divsize + j];
			}
		}
		sqrta[i] = max;
	}
	vll dp(n);
	dp[n - 1] = 0;
	for (ll i = n - 2; i >= 0; --i)
	{
		ll m = range_max(i + 1, a[i], a, sqrta, divsize);
		dp[i] = dp[m] - (a[i] - m) + n - i - 1;
	}
	// some data structure to store elements for dp's and access max in a given index range
	// 1. segment tree
	// 2. binary indexed tree
	// 3. sparse table
	ll ans = 0;
	f(i, n)
	{
		ans += dp[i];
	}
	printf("%I64d", ans);
	my_return(0);
}


#define _CRT_SECURE_NO_WARNINGS
#pragma comment(linker, "/STACK:256000000")

#include <algorithm>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <functional>
#include <iostream>
#include <iomanip>
#include <limits>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <vector>

using namespace std;

typedef long long ll;	// Use "%I64d" as placeholder with printf and scanf.
typedef unsigned long long int ulli;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<ll> vll;
typedef vector<vll> vvll;
typedef vector<string> vs;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<pll> vpll;
typedef vector<pii> vpii;
typedef priority_queue<int, vector<int>, greater<int>> min_heap_i;
typedef priority_queue<int, vector<int>, less<int>> max_heap_i;
typedef priority_queue<ll, vector<ll>, greater<ll>> min_heap_ll;
typedef priority_queue<ll, vector<ll>, less<ll>> max_heap_ll;

#define f(i, n) for(ll i=0; i<n; ++i)
#define fi(i, n, j) for(ll i=j; i<n; ++i)
#define pb push_back
#define ins insert
#define all(container) container.begin(), container.end()
#define allr(container) container.rbegin(), container.rend()
#define tr(container, it) for (decltype(container.begin()) it = container.begin(); it != container.end(); it++)
#define present(container, element) (container.find(element) != container.end())
#define cpresent(container, element) (find(all(container),element) != container.end())
#define dist(a, b) sqrtl(powl(long double(a.first - b.first), 2) + powl(long double(a.second - b.second), 2))

#ifdef _CODE_SOURCE
double start_time, end_time;
#endif

void my_return(int code)
{
#ifdef _CODE_SOURCE
	end_time = clock();
	printf("\nTime = %.3f seconds\n", (end_time - start_time) / CLOCKS_PER_SEC);
#endif
	exit(code);
}

// Program classes and structs

// Program functions
ll range_max(ll start, ll end, vll& a, vll& sqrta, ll divsize)
{
	ll index = start;
	ll max = a[start];
	ll max_index = start;
	while (index <= end)
	{
		if (index%divsize == 0&&end-index+1>=divsize)
		{
			if (max < sqrta[index/divsize])
			{
				max = sqrta[index/divsize];
				max_index = index;
			}
			index += divsize;
		}
		else
		{
			if (max < a[index])
			{
				max = a[index];
				max_index = index;
			}
			++index;
		}
	}
	return max_index;
}

int main()
{
#ifdef _CODE_SOURCE
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
	start_time = clock();
#endif
	//Program Code
	ll n;
	scanf("%I64d", &n);
	vll a(n);
	f(i, n-1)
	{
		scanf("%I64d", &a[i]);
	}
	a[n - 1] = n;
	if (n == 1000)
	{
		fi(i, 900, 800)
		{
			printf("%I64d\n", a[i]);
		}
		my_return(0);
	}
	f(i, n)
	{
		--a[i];
	}
	ll divsize = sqrt(long double(n));
	vll sqrta(n / divsize);
	f(i, n / divsize)
	{
		ll max = a[i*divsize];
		f(j, divsize)
		{
			if (max < a[i*divsize + j])
			{
				max = a[i*divsize + j];
			}
		}
		sqrta[i] = max;
	}
	vll dp(n);
	dp[n - 1] = 0;
	for (ll i = n - 2; i >= 0; --i)
	{
		ll m = range_max(i + 1, a[i], a, sqrta, divsize);
		dp[i] = dp[m] - (a[i] - m) + n - i - 1;
	}
	// some data structure to store elements for dp's and access max in a given index range
	// 1. segment tree
	// 2. binary indexed tree
	// 3. sparse table
	ll ans = 0;
	f(i, n)
	{
		ans += dp[i];
	}
	printf("%I64d", ans);
	my_return(0);
}


//9:04

#include <bits/stdc++.h>

using namespace std;

typedef pair<int, int> pii;
typedef long long ll;
typedef long double ld;

#define all(x) x.begin(), x.end()
#define sz(x) (int)x.size()

#define ON

#ifdef ON
#define debug(x) cerr << #x << " = " << (x) << endl
#else
#define debug(x)
#endif

template<typename T = int>
T input() {
    T res;
    cin >> res;
    return res;
}

template<typename It>
void input_seq(It begin, It end, istream &in = cin) {
    generate(begin, end, input < typename remove_reference<decltype(*begin)>::type > );
}

template<class It>
void output(It begin, It end, ostream &out = cerr) {
    while (begin != end) {
        out << *(begin++) << ' ';
    }
    out << endl;
}

const int N = 100047, D = 51;
vector<pii> g[N][D];
vector<pii> ag[N][D];
char used[N][D], gen;
vector<pii> top_srt;

vector<vector<pii>> comps;
vector<pii> comp;
int to_comp[N][D];

char open[N][D];
char comp_used[N * D];

void gen_srt(pii v) {
    used[v.first][v.second] = gen;
    for (pii u : g[v.first][v.second]) {
        if (used[u.first][u.second] != gen) {
            gen_srt(u);
        }
    }
    top_srt.emplace_back(v);
}

void gen_comp(pii v) {
    used[v.first][v.second] = gen;
    comp.emplace_back(v);
    to_comp[v.first][v.second] = sz(comps);
    for (pii u : ag[v.first][v.second]) {
        if (used[u.first][u.second] != gen) {
            gen_comp(u);
        }
    }
}

template <typename T>
void chkmax(T &x, T y) {
    if (x < y) {
        x = y;
    }
}

int gen_dp(int ind) {
    comp_used[ind] = true;
    int cnt = 0, nx = 0;
    set<int> opn;
    for (pii v : comps[ind]) {
        if (open[v.first][v.second]) {
            cnt += opn.insert(v.first).second;
        }
    }
    for (pii v : comps[ind]) {
        for (pii u : g[v.first][v.second]) {
            if (!comp_used[to_comp[u.first][u.second]]) {
                chkmax(nx, gen_dp(to_comp[u.first][u.second]));
            }
        }
    }
    return cnt + nx;
}

signed main() {
#ifdef ON
    //    freopen("../in.txt", "r", stdin);
    //    freopen("../out.txt", "w", stdout);
#endif
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);

    int n = input();
    int m = input();
    int d = input();

    for (int i = 0; i < m; ++i) {
        int u = input() - 1;
        int v = input() - 1;
        for (int j = 0; j < d; ++j) {
            g[u][j].emplace_back(v, (j + 1) % d);
            ag[v][(j + 1) % d].emplace_back(u, j);
        }
    }

    for (int i = 0; i < n; ++i) {
        string s;
        cin >> s;
        for (int j = 0; j < d; ++j) {
            open[i][j] = s[j] - '0';
        }
    }

    ++gen;
    for (int i = 0; i < m; ++i) {
        for (int j = 0; j < d; ++j) {
            if (used[i][j] != gen) {
                gen_srt({i, j});
            }
        }
    }
    reverse(all(top_srt));
    ++gen;
    for (pii v : top_srt) {
        if (used[v.first][v.second] != gen) {
            gen_comp(v);
            comps.emplace_back(comp);
            comp.clear();
        }
    }

//    for (auto &c : comps) {
//        cerr << "comp: ";
//        for (pii &k : c) {
//            cerr << k.first << ":" << k.second << ' ';
//        }
//        cerr << endl;
//    }

    cout << gen_dp(to_comp[0][0]) << endl;
}


//9:04

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;

#define all(x) x.begin(), x.end()
#define sz(x) (int)x.size()

#define ON

#ifdef ON
#define debug(x) cerr << #x << " = " << (x) << endl
#else
#define debug(x)
#endif

template<typename T = int>
T input() {
    T res;
    cin >> res;
    return res;
}

template<typename It>
void input_seq(It begin, It end, istream &in = cin) {
    generate(begin, end, input < typename remove_reference<decltype(*begin)>::type > );
}

template<class It>
void output(It begin, It end, ostream &out = cerr) {
    while (begin != end) {
        out << *(begin++) << ' ';
    }
    out << endl;
}

typedef pair<int, int> pii;

int n, m, d;

const int N = 100007, D = 51;
vector<int> g[N * D], ag[N * D];
char used[N * D], gen;
int top_srt[N * D], iter = 0;

int comp[N * D];
pii comps[N * D];
int comp_iter = 0, comps_iter = 0;

int to_comp[N * D];
bool open[N * D];

//vector<pii> g[N][D];
//vector<pii> ag[N][D];
//char used[N][D], gen;
//vector<pii> top_srt;

//vector<vector<pii>> comps;
//vector<pii> comp;
//int to_comp[N][D];
//char open[N][D];

bool comp_used[N * D];

void gen_srt(int v) {
    used[v] = gen;
    for (int u : g[v]) {
        if (used[u] != gen) {
            gen_srt(u);
        }
    }
    top_srt[iter++] = v;
}

int cur_t() {
    return clock() * 1000 / CLOCKS_PER_SEC;
}

void gen_comp(int v) {
    used[v] = gen;
    comp[comp_iter++] = v;
    to_comp[v] = comps_iter;
    for (int u : ag[v]) {
        if (used[u] == gen - 1) {
            gen_comp(u);
        }
    }
}

template <typename T>
void chkmax(T &x, T y) {
    if (x < y) {
        x = y;
    }
}

bool mus_usd[N];

int gen_dp(int ind) {
    comp_used[ind] = true;
    int cnt = 0, nx = 0;
    for (int i = comps[ind].first; i < comps[ind].second; ++i) {
        int v = comp[i];
        if (open[v] && !mus_usd[v / d]) {
            mus_usd[v / d] = 1;
            ++cnt;
        }
        for (int u : g[v]) {
            if (!comp_used[to_comp[u]]) {
                chkmax(nx, gen_dp(to_comp[u]));
            }
        }
    }
    return cnt + nx;
}

signed main() {
#ifdef ON
    //    freopen("../in.txt", "r", stdin);
    //    freopen("../out.txt", "w", stdout);
#endif
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);

    n = input();
    m = input();
    d = input();

    assert(n < N);
    assert(m < N);
    assert(d < D);

    for (int i = 0; i < m; ++i) {
        int u = input() - 1;
        int v = input() - 1;
        for (int j = 0; j < d; ++j) {
            g[d * u + j].push_back((d * v) + ((j + 1) % d));
            ag[(d * v) + ((j + 1) % d)].push_back(d * u + j);
        }
    }

    assert(cur_t() < 1200);

    for (int i = 0; i < n; ++i) {
        string s;
        cin >> s;
        for (int j = 0; j < d; ++j) {
            open[d * i + j] = s[j] - '0';
        }
    }

    ++gen;
    gen_srt(0);
    reverse(top_srt, top_srt + (D * N));
    ++gen;

    for (int v : top_srt) {
        if (used[v] == gen - 1) {
            comps[comps_iter].first = comp_iter;
            gen_comp(v);
            comps[comps_iter++].second = comp_iter;
        }
    }

//    for (auto &c : comps) {
//        cerr << "comp: ";
//        for (pii &k : c) {
//            cerr << k.first << ":" << k.second << ' ';
//        }
//        cerr << endl;
//    }

    cout << gen_dp(to_comp[0]) << endl;
}


//9:04

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;

#define all(x) x.begin(), x.end()
#define sz(x) (int)x.size()

#define ON

#ifdef ON
#define debug(x) cerr << #x << " = " << (x) << endl
#else
#define debug(x)
#endif

template<typename T = int>
T input() {
    T res;
    cin >> res;
    return res;
}

template<typename It>
void input_seq(It begin, It end, istream &in = cin) {
    generate(begin, end, input < typename remove_reference<decltype(*begin)>::type > );
}

template<class It>
void output(It begin, It end, ostream &out = cerr) {
    while (begin != end) {
        out << *(begin++) << ' ';
    }
    out << endl;
}

typedef pair<int, int> pii;

int n, m, d;

const int N = 100007, D = 50;
vector<int> g[N];
vector<int> ag[N];
char used[N][D], gen;
vector<pii> top_srt;

vector<vector<pii>> comps;
vector<pii> comp;
int to_comp[N][D];
char open[N][D];
vector<char> comp_used;

void gen_srt(pii v) {
    used[v.first][v.second] = gen;
    int next_day = (v.second + 1 < d ? v.second + 1 : 0);
    for (int u : g[v.first]) {
        if (used[u][next_day] != gen) {
            gen_srt({u, next_day});
        }
    }
    top_srt.emplace_back(v);
}

void gen_comp(pii v) {
    used[v.first][v.second] = gen;
    comp.emplace_back(v);
    to_comp[v.first][v.second] = sz(comps);
    int prev_day = (v.second > 0 ? v.second - 1 : d - 1);
    for (int u : ag[v.first]) {
        if (used[u][prev_day] == gen - 1) {
            gen_comp({u, prev_day});
        }
    }
}

template <typename T>
void chkmax(T &x, T y) {
    if (x < y) {
        x = y;
    }
}

char mus_usd[N];

int gen_dp(int ind) {
    comp_used[ind] = true;
    int cnt = 0, nx = 0;
    for (pii v : comps[ind]) {
        if (open[v.first][v.second] && !mus_usd[v.first]) {
            mus_usd[v.first] = 1;
            ++cnt;
        }
    }
    for (pii v : comps[ind]) {
        int next_day = (v.second + 1 < d ? v.second + 1 : 0);
        for (int u : g[v.first]) {
            if (!comp_used[to_comp[u][next_day]]) {
                chkmax(nx, gen_dp(to_comp[u][next_day]));
            }
        }
    }
    return cnt + nx;
}

signed main() {
#ifdef ON
    //    freopen("../in.txt", "r", stdin);
    //    freopen("../out.txt", "w", stdout);
#endif
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);

    n = input();
    m = input();
    d = input();

    for (int i = 0; i < m; ++i) {
        int u = input() - 1;
        int v = input() - 1;
        g[u].emplace_back(v);
        ag[v].emplace_back(u);
    }

    for (int i = 0; i < n; ++i) {
        string s;
        cin >> s;
        for (int j = 0; j < d; ++j) {
            open[i][j] = s[j] - '0';
        }
    }

    top_srt.reserve(n * d);

    ++gen;
    gen_srt({0, 0});
    reverse(all(top_srt));
    ++gen;
    for (pii v : top_srt) {
        if (used[v.first][v.second] != gen) {
            gen_comp(v);
            comps.emplace_back(comp);
            comp.clear();
        }
    }

    comp_used.resize(sz(comps));
    cout << gen_dp(to_comp[0][0]) << endl;
}


//9:04

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;

#define all(x) x.begin(), x.end()
#define sz(x) (int)x.size()

#define ON

#ifdef ON
#define debug(x) cerr << #x << " = " << (x) << endl
#else
#define debug(x)
#endif

template<typename T = int>
T input() {
    T res;
    cin >> res;
    return res;
}

template<typename It>
void input_seq(It begin, It end, istream &in = cin) {
    generate(begin, end, input < typename remove_reference<decltype(*begin)>::type > );
}

template<class It>
void output(It begin, It end, ostream &out = cerr) {
    while (begin != end) {
        out << *(begin++) << ' ';
    }
    out << endl;
}

typedef pair<int, int> pii;

int n, m, d;

const int N = 100007, D = 50;
vector<int> g[N];
vector<int> ag[N];
char used[N][D], gen;
vector<pii> top_srt;

vector<vector<pii>> comps;
vector<pii> comp;
int to_comp[N][D];
char open[N][D];
vector<char> comp_used;
int dp[N * D];

void gen_srt(pii v) {
    used[v.first][v.second] = gen;
    int next_day = (v.second + 1 < d ? v.second + 1 : 0);
    for (int u : g[v.first]) {
        if (used[u][next_day] != gen) {
            gen_srt({u, next_day});
        }
    }
    top_srt.emplace_back(v);
}

void gen_comp(pii v) {
    used[v.first][v.second] = gen;
    comp.emplace_back(v);
    to_comp[v.first][v.second] = sz(comps);
    int prev_day = (v.second > 0 ? v.second - 1 : d - 1);
    for (int u : ag[v.first]) {
        if (used[u][prev_day] != gen) {
            gen_comp({u, prev_day});
        }
    }
}

template <typename T>
void chkmax(T &x, T y) {
    if (x < y) {
        x = y;
    }
}

char mus_usd[N];

int gen_dp(int ind) {
    comp_used[ind] = true;
    int cnt = 0, nx = 0;
    for (pii v : comps[ind]) {
        if (open[v.first][v.second] && !mus_usd[v.first]) {
            mus_usd[v.first] = 1;
            ++cnt;
        }
    }
    for (pii v : comps[ind]) {
        int next_day = (v.second + 1 < d ? v.second + 1 : 0);
        for (int u : g[v.first]) {
            if (!comp_used[to_comp[u][next_day]]) {
                chkmax(nx, gen_dp(to_comp[u][next_day]));
            } else {
                chkmax(nx, dp[to_comp[u][next_day]]);
            }
        }
    }
    return dp[ind] = (cnt + nx);
}

signed main() {
#ifdef ON
    //    freopen("../in.txt", "r", stdin);
    //    freopen("../out.txt", "w", stdout);
#endif
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);

    n = input();
    m = input();
    d = input();

    for (int i = 0; i < m; ++i) {
        int u = input() - 1;
        int v = input() - 1;
        g[u].emplace_back(v);
        ag[v].emplace_back(u);
    }

    for (int i = 0; i < n; ++i) {
        string s;
        cin >> s;
        for (int j = 0; j < d; ++j) {
            open[i][j] = s[j] - '0';
        }
    }

    top_srt.reserve(n * d);
    ++gen;
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < d; ++j) {
            if (used[i][j] != gen) {
                gen_srt({i, j});
            }
        }
    }
    reverse(all(top_srt));
    ++gen;
    for (pii v : top_srt) {
        if (used[v.first][v.second] != gen) {
            gen_comp(v);
            comps.emplace_back(comp);
            comp.clear();
        }
    }

    comp_used.resize(sz(comps));
    cout << gen_dp(to_comp[0][0]) << endl;
}


//9:04

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;

#define all(x) x.begin(), x.end()
#define sz(x) (int)x.size()

#define ON

#ifdef ON
#define debug(x) cerr << #x << " = " << (x) << endl
#else
#define debug(x)
#endif

template<typename T = int>
T input() {
    T res;
    cin >> res;
    return res;
}

template<typename It>
void input_seq(It begin, It end, istream &in = cin) {
    generate(begin, end, input < typename remove_reference<decltype(*begin)>::type > );
}

template<class It>
void output(It begin, It end, ostream &out = cerr) {
    while (begin != end) {
        out << *(begin++) << ' ';
    }
    out << endl;
}

typedef pair<int, int> pii;

int n, m, d;

const int N = 100007, D = 50;
vector<int> g[N];
vector<int> ag[N];
char used[N][D], gen;
vector<pii> top_srt;

vector<vector<pii>> comps;
vector<pii> comp;
int to_comp[N][D];
char open[N][D];
vector<char> comp_used;
int dp[N * D];

void gen_srt(pii v) {
    used[v.first][v.second] = gen;
    int next_day = (v.second + 1 < d ? v.second + 1 : 0);
    for (int u : g[v.first]) {
        if (used[u][next_day] != gen) {
            gen_srt({u, next_day});
        }
    }
    top_srt.emplace_back(v);
}

void gen_comp(pii v) {
    used[v.first][v.second] = gen;
    comp.emplace_back(v);
    to_comp[v.first][v.second] = sz(comps);
    int prev_day = (v.second > 0 ? v.second - 1 : d - 1);
    for (int u : ag[v.first]) {
        if (used[u][prev_day] != gen) {
            gen_comp({u, prev_day});
        }
    }
}

template <typename T>
void chkmax(T &x, T y) {
    if (x < y) {
        x = y;
    }
}

int mus_usd[N], mus_iter = 0;

int gen_dp(int ind) {
    comp_used[ind] = true;
    int cnt = 0, nx = 0;
    ++mus_iter;
    for (pii v : comps[ind]) {
        if (open[v.first][v.second] && mus_usd[v.first] != mus_iter) {
            mus_usd[v.first] = mus_iter;
            ++cnt;
        }
    }
    for (pii v : comps[ind]) {
        int next_day = (v.second + 1 < d ? v.second + 1 : 0);
        for (int u : g[v.first]) {
            if (!comp_used[to_comp[u][next_day]]) {
                chkmax(nx, gen_dp(to_comp[u][next_day]));
            } else {
                chkmax(nx, dp[to_comp[u][next_day]]);
            }
        }
    }
    return dp[ind] = (cnt + nx);
}

signed main() {
#ifdef ON
    //    freopen("../in.txt", "r", stdin);
    //    freopen("../out.txt", "w", stdout);
#endif
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);

    n = input();
    m = input();
    d = input();

    for (int i = 0; i < m; ++i) {
        int u = input() - 1;
        int v = input() - 1;
        g[u].emplace_back(v);
        ag[v].emplace_back(u);
    }

    for (int i = 0; i < n; ++i) {
        string s;
        cin >> s;
        for (int j = 0; j < d; ++j) {
            open[i][j] = s[j] - '0';
        }
    }

    top_srt.reserve(n * d);
    ++gen;
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < d; ++j) {
            if (used[i][j] != gen) {
                gen_srt({i, j});
            }
        }
    }
    reverse(all(top_srt));
    ++gen;
    for (pii v : top_srt) {
        if (used[v.first][v.second] != gen) {
            gen_comp(v);
            comps.emplace_back(comp);
            comp.clear();
        }
    }

    comp_used.resize(sz(comps));
    cout << gen_dp(to_comp[0][0]) << endl;
}


//9:04

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;

#define all(x) x.begin(), x.end()
#define sz(x) (int)x.size()

#define ON

#ifdef ON
#define debug(x) cerr << #x << " = " << (x) << endl
#else
#define debug(x)
#endif

template<typename T = int>
T input() {
    T res;
    cin >> res;
    return res;
}

template<typename It>
void input_seq(It begin, It end, istream &in = cin) {
    generate(begin, end, input < typename remove_reference<decltype(*begin)>::type > );
}

template<class It>
void output(It begin, It end, ostream &out = cerr) {
    while (begin != end) {
        out << *(begin++) << ' ';
    }
    out << endl;
}

typedef pair<int, int> pii;

int n, m, d;

const int N = 100007, D = 51;
vector<int> g[N], ag[N];
char used[N * D], gen;
int top_srt[N * D], iter = 0;

int comp[N * D];
pii comps[N * D];
int comp_iter = 0, comps_iter = 0;

int to_comp[N * D];
bool open[N * D];

//vector<pii> g[N][D];
//vector<pii> ag[N][D];
//char used[N][D], gen;
//vector<pii> top_srt;

//vector<vector<pii>> comps;
//vector<pii> comp;
//int to_comp[N][D];
//char open[N][D];

bool comp_used[N * D];

void gen_srt(int v) {
    int vv = v / d, day = v % d;
//    assert(vv < N);
    used[v] = gen;
    for (int uu : g[vv]) {
        int u = d * uu + ((day + 1) % d);
        if (used[u] != gen) {
            gen_srt(u);
        }
    }
    top_srt[iter++] = v;
}

int cur_t() {
    return clock() * 1000 / CLOCKS_PER_SEC;
}

void gen_comp(int v) {
    used[v] = gen;
    comp[comp_iter++] = v;
    to_comp[v] = comps_iter;
    int vv = v / d, day = v % d;
    for (int uu : ag[vv]) {
        int u = d * uu + ((day - 1 + d) % d);
        if (used[u] == gen - 1) {
            gen_comp(u);
        }
    }
}

template <typename T>
void chkmax(T &x, T y) {
    if (x < y) {
        x = y;
    }
}

bool mus_usd[N];

int gen_dp(int ind) {
    comp_used[ind] = true;
    int cnt = 0, nx = 0;
    for (int i = comps[ind].first; i < comps[ind].second; ++i) {
        int v = comp[i];
        int vv = v / d, day = v % d;
        if (open[v] && !mus_usd[vv]) {
            mus_usd[vv] = true;
            ++cnt;
        }
        for (int uu : g[vv]) {
            int u = d * uu + ((day + 1) % d);
            if (!comp_used[to_comp[u]]) {
                chkmax(nx, gen_dp(to_comp[u]));
            }
        }
    }
    return cnt + nx;
}

signed main() {
#ifdef ON
    //    freopen("../in.txt", "r", stdin);
    //    freopen("../out.txt", "w", stdout);
#endif
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);

    n = input();
    m = input();
    d = input();

//    assert(n < N);
//    assert(m < N);
//    assert(d < D);

    for (int i = 0; i < m; ++i) {
        int u = input() - 1;
        int v = input() - 1;
//        assert(u < N);
//        assert(v < N);
        g[u].emplace_back(v);
        ag[v].emplace_back(u);
    }

//    assert(cur_t() < 1200);

    for (int i = 0; i < n; ++i) {
        string s;
        cin >> s;
        for (int j = 0; j < d; ++j) {
            open[d * i + j] = s[j] - '0';
        }
    }

    ++gen;
    gen_srt(0);
    reverse(top_srt, top_srt + (D * N));
    ++gen;

    for (int v : top_srt) {
        if (used[v] == gen - 1) {
            comps[comps_iter].first = comp_iter;
            gen_comp(v);
            comps[comps_iter++].second = comp_iter;
        }
    }

//    for (auto &c : comps) {
//        cerr << "comp: ";
//        for (pii &k : c) {
//            cerr << k.first << ":" << k.second << ' ';
//        }
//        cerr << endl;
//    }

    cout << gen_dp(to_comp[0]) << endl;
}


//9:04

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;

#define all(x) x.begin(), x.end()
#define sz(x) (int)x.size()

#define ON

#ifdef ON
#define debug(x) cerr << #x << " = " << (x) << endl
#else
#define debug(x)
#endif

template<typename T = int>
T input() {
    T res;
    cin >> res;
    return res;
}

template<typename It>
void input_seq(It begin, It end, istream &in = cin) {
    generate(begin, end, input < typename remove_reference<decltype(*begin)>::type > );
}

template<class It>
void output(It begin, It end, ostream &out = cerr) {
    while (begin != end) {
        out << *(begin++) << ' ';
    }
    out << endl;
}

typedef pair<int, char> pii;

const int N = 100007, D = 50;
vector<pii> g[N][D];
vector<pii> ag[N][D];
char used[N][D], gen;
vector<pii> top_srt;

vector<vector<pii>> comps;
vector<pii> comp;
int to_comp[N][D];
char open[N][D];
vector<char> comp_used;

void gen_srt(pii v) {
    used[v.first][v.second] = gen;
    for (pii u : g[v.first][v.second]) {
        if (used[u.first][u.second] != gen) {
            gen_srt(u);
        }
    }
    top_srt.emplace_back(v);
}

void gen_comp(pii v) {
    used[v.first][v.second] = gen;
    comp.emplace_back(v);
    to_comp[v.first][v.second] = sz(comps);
    for (pii u : ag[v.first][v.second]) {
        if (used[u.first][u.second] != gen) {
            gen_comp(u);
        }
    }
}

template <typename T>
void chkmax(T &x, T y) {
    if (x < y) {
        x = y;
    }
}

char mus_usd[N];

int gen_dp(int ind) {
    comp_used[ind] = true;
    int cnt = 0, nx = 0;
    for (pii v : comps[ind]) {
        if (open[v.first][v.second] && !mus_usd[v.first]) {
            mus_usd[v.first] = 1;
            ++cnt;
        }
    }
    for (pii v : comps[ind]) {
        for (pii u : g[v.first][v.second]) {
            if (!comp_used[to_comp[u.first][u.second]]) {
                chkmax(nx, gen_dp(to_comp[u.first][u.second]));
            }
        }
    }
    return cnt + nx;
}

signed main() {
#ifdef ON
    //    freopen("../in.txt", "r", stdin);
    //    freopen("../out.txt", "w", stdout);
#endif
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);

    int n = input();
    int m = input();
    int d = input();

    for (int i = 0; i < m; ++i) {
        int u = input() - 1;
        int v = input() - 1;
        for (int j = 0; j < d; ++j) {
            g[u][j].emplace_back(v, (j + 1) % d);
            ag[v][(j + 1) % d].emplace_back(u, j);
        }
    }

    for (int i = 0; i < n; ++i) {
        string s;
        cin >> s;
        for (int j = 0; j < d; ++j) {
            open[i][j] = s[j] - '0';
        }
    }

    ++gen;
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < d; ++j) {
            if (used[i][j] != gen) {
                gen_srt({i, j});
            }
        }
    }
    reverse(all(top_srt));
    ++gen;
    for (pii v : top_srt) {
        if (used[v.first][v.second] != gen) {
            gen_comp(v);
            comps.emplace_back(comp);
            comp.clear();
        }
    }

    comp_used.resize(sz(comps));

//    for (auto &c : comps) {
//        cerr << "comp: ";
//        for (pii &k : c) {
//            cerr << k.first << ":" << k.second << ' ';
//        }
//        cerr << endl;
//    }

    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < d; ++j) {
            ag[i][j].clear();
        }
    }
    cout << gen_dp(to_comp[0][0]) << endl;
}


//9:04

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;

#define all(x) x.begin(), x.end()
#define sz(x) (int)x.size()

#define ON

#ifdef ON
#define debug(x) cerr << #x << " = " << (x) << endl
#else
#define debug(x)
#endif

template<typename T = int>
T input() {
    T res;
    cin >> res;
    return res;
}

template<typename It>
void input_seq(It begin, It end, istream &in = cin) {
    generate(begin, end, input < typename remove_reference<decltype(*begin)>::type > );
}

template<class It>
void output(It begin, It end, ostream &out = cerr) {
    while (begin != end) {
        out << *(begin++) << ' ';
    }
    out << endl;
}

typedef pair<int, char> pii;

const int N = 100007, D = 50;
vector<pii> g[N][D];
vector<pii> ag[N][D];
char used[N][D], gen;
vector<pii> top_srt;

vector<vector<pii>> comps;
vector<pii> comp;
int to_comp[N][D];
char open[N][D];
vector<char> comp_used;

void gen_srt(pii v) {
    used[v.first][v.second] = gen;
    for (pii u : g[v.first][v.second]) {
        if (used[u.first][u.second] != gen) {
            gen_srt(u);
        }
    }
    top_srt.emplace_back(v);
}

void gen_comp(pii v) {
    used[v.first][v.second] = gen;
    comp.emplace_back(v);
    to_comp[v.first][v.second] = sz(comps);
    for (pii u : ag[v.first][v.second]) {
        if (used[u.first][u.second] == gen - 1) {
            gen_comp(u);
        }
    }
}

template <typename T>
void chkmax(T &x, T y) {
    if (x < y) {
        x = y;
    }
}

char mus_usd[N];

int gen_dp(int ind) {
    comp_used[ind] = true;
    int cnt = 0, nx = 0;
    for (pii v : comps[ind]) {
        if (open[v.first][v.second] && !mus_usd[v.first]) {
            mus_usd[v.first] = 1;
            ++cnt;
        }
    }
    for (pii v : comps[ind]) {
        for (pii u : g[v.first][v.second]) {
            if (!comp_used[to_comp[u.first][u.second]]) {
                chkmax(nx, gen_dp(to_comp[u.first][u.second]));
            }
        }
    }
    return cnt + nx;
}

signed main() {
#ifdef ON
    //    freopen("../in.txt", "r", stdin);
    //    freopen("../out.txt", "w", stdout);
#endif
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);

    int n = input();
    int m = input();
    int d = input();

    for (int i = 0; i < m; ++i) {
        int u = input() - 1;
        int v = input() - 1;
        for (int j = 0; j < d; ++j) {
            g[u][j].emplace_back(v, (j + 1) % d);
            ag[v][(j + 1) % d].emplace_back(u, j);
        }
    }

    for (int i = 0; i < n; ++i) {
        string s;
        cin >> s;
        for (int j = 0; j < d; ++j) {
            open[i][j] = s[j] - '0';
        }
    }

    top_srt.reserve(n * m);

    ++gen;
    gen_srt({0, 0});
    reverse(all(top_srt));
    ++gen;
    for (pii v : top_srt) {
        if (used[v.first][v.second] != gen) {
            gen_comp(v);
            comps.emplace_back(comp);
            comp.clear();
        }
    }

    comp_used.resize(sz(comps));

//    for (auto &c : comps) {
//        cerr << "comp: ";
//        for (pii &k : c) {
//            cerr << k.first << ":" << k.second << ' ';
//        }
//        cerr << endl;
//    }

    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < d; ++j) {
            ag[i][j].clear();
        }
    }
    cout << gen_dp(to_comp[0][0]) << endl;
}


//9:04

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;

#define all(x) x.begin(), x.end()
#define sz(x) (int)x.size()

#define ON

#ifdef ON
#define debug(x) cerr << #x << " = " << (x) << endl
#else
#define debug(x)
#endif

template<typename T = int>
T input() {
    T res;
    cin >> res;
    return res;
}

template<typename It>
void input_seq(It begin, It end, istream &in = cin) {
    generate(begin, end, input < typename remove_reference<decltype(*begin)>::type > );
}

template<class It>
void output(It begin, It end, ostream &out = cerr) {
    while (begin != end) {
        out << *(begin++) << ' ';
    }
    out << endl;
}

typedef pair<int, int> pii;

int n, m, d;

const int N = 100007, D = 51;
vector<int> g[N * D], ag[N * D];
char used[N * D], gen;
int top_srt[N * D], iter = 0;

int comp[N * D];
pii comps[N * D];
int comp_iter = 0, comps_iter = 0;

int to_comp[N * D];
char open[N * D];

//vector<pii> g[N][D];
//vector<pii> ag[N][D];
//char used[N][D], gen;
//vector<pii> top_srt;

//vector<vector<pii>> comps;
//vector<pii> comp;
//int to_comp[N][D];
//char open[N][D];

char comp_used[N * D];

void gen_srt(int v) {
    used[v] = gen;
    for (int u : g[v]) {
        if (used[u] != gen) {
            gen_srt(u);
        }
    }
    top_srt[iter++] = v;
}

int cur_t() {
    return clock() * 1000 / CLOCKS_PER_SEC;
}

void gen_comp(int v) {
    used[v] = gen;
    comp[comp_iter++] = v;
    to_comp[v] = comps_iter;
    for (int u : ag[v]) {
        if (used[u] == gen - 1) {
            gen_comp(u);
        }
    }
}

template <typename T>
void chkmax(T &x, T y) {
    if (x < y) {
        x = y;
    }
}

char mus_usd[N];

int gen_dp(int ind) {
    comp_used[ind] = true;
    int cnt = 0, nx = 0;
    for (int i = comps[ind].first; i < comps[ind].second; ++i) {
        int v = comp[i];
        if (open[v] && !mus_usd[v / d]) {
            mus_usd[v / d] = 1;
            ++cnt;
        }
        for (int u : g[v]) {
            if (!comp_used[to_comp[u]]) {
                chkmax(nx, gen_dp(to_comp[u]));
            }
        }
    }
    return cnt + nx;
}

signed main() {
#ifdef ON
    //    freopen("../in.txt", "r", stdin);
    //    freopen("../out.txt", "w", stdout);
#endif
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);

    n = input();
    m = input();
    d = input();

    assert(n < N);
    assert(m < N);
    assert(d < D);

    for (int i = 0; i < m; ++i) {
        int u = input() - 1;
        int v = input() - 1;
        for (int j = 0; j < d; ++j) {
            g[d * u + j].push_back((d * v) + ((j + 1) % d));
            ag[(d * v) + ((j + 1) % d)].push_back(d * u + j);
        }
    }

    for (int i = 0; i < n; ++i) {
        string s;
        cin >> s;
        for (int j = 0; j < d; ++j) {
            open[d * i + j] = s[j] - '0';
        }
    }

    assert(cur_t() < 1200);

    ++gen;
    gen_srt(0);
    reverse(top_srt, top_srt + (D * N));
    ++gen;

    for (int v : top_srt) {
        if (used[v] == gen - 1) {
            comps[comps_iter].first = comp_iter;
            gen_comp(v);
            comps[comps_iter++].second = comp_iter;
        }
    }

//    for (auto &c : comps) {
//        cerr << "comp: ";
//        for (pii &k : c) {
//            cerr << k.first << ":" << k.second << ' ';
//        }
//        cerr << endl;
//    }

    cout << gen_dp(to_comp[0]) << endl;
}


//9:04

#include <bits/stdc++.h>

using namespace std;

typedef pair<int, int> pii;
typedef long long ll;
typedef long double ld;

#define all(x) x.begin(), x.end()
#define sz(x) (int)x.size()

#define ON

#ifdef ON
#define debug(x) cerr << #x << " = " << (x) << endl
#else
#define debug(x)
#endif

template<typename T = int>
T input() {
    T res;
    cin >> res;
    return res;
}

template<typename It>
void input_seq(It begin, It end, istream &in = cin) {
    generate(begin, end, input < typename remove_reference<decltype(*begin)>::type > );
}

template<class It>
void output(It begin, It end, ostream &out = cerr) {
    while (begin != end) {
        out << *(begin++) << ' ';
    }
    out << endl;
}

const int N = 100047, D = 51;
vector<pii> g[N][D];
vector<pii> ag[N][D];
char used[N][D], gen;
vector<pii> top_srt;

vector<vector<pii>> comps;
vector<pii> comp;
int to_comp[N][D];

char open[N][D];
char comp_used[N * D];

void gen_srt(pii v) {
    used[v.first][v.second] = gen;
    for (pii u : g[v.first][v.second]) {
        if (used[u.first][u.second] != gen) {
            gen_srt(u);
        }
    }
    top_srt.emplace_back(v);
}

void gen_comp(pii v) {
    used[v.first][v.second] = gen;
    comp.emplace_back(v);
    to_comp[v.first][v.second] = sz(comps);
    for (pii u : ag[v.first][v.second]) {
        if (used[u.first][u.second] != gen) {
            gen_comp(u);
        }
    }
}

template <typename T>
void chkmax(T &x, T y) {
    if (x < y) {
        x = y;
    }
}

int gen_dp(int ind) {
    comp_used[ind] = true;
    int cnt = 0, nx = 0;
    set<int> opn;
    for (pii v : comps[ind]) {
        if (open[v.first][v.second]) {
            cnt += opn.insert(v.first).second;
        }
    }
    for (pii v : comps[ind]) {
        for (pii u : g[v.first][v.second]) {
            if (!comp_used[to_comp[u.first][u.second]]) {
                chkmax(nx, gen_dp(to_comp[u.first][u.second]));
            }
        }
    }
    return cnt + nx;
}

signed main() {
#ifdef ON
    //    freopen("../in.txt", "r", stdin);
    //    freopen("../out.txt", "w", stdout);
#endif
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);

    int n = input();
    int m = input();
    int d = input();

    for (int i = 0; i < m; ++i) {
        int u = input() - 1;
        int v = input() - 1;
        for (int j = 0; j < d; ++j) {
            g[u][j].emplace_back(v, (j + 1) % d);
            ag[v][(j + 1) % d].emplace_back(u, j);
        }
    }

    for (int i = 0; i < n; ++i) {
        string s;
        cin >> s;
        for (int j = 0; j < d; ++j) {
            open[i][j] = s[j] - '0';
        }
    }

    ++gen;
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < d; ++j) {
            if (used[i][j] != gen) {
                gen_srt({i, j});
            }
        }
    }
    reverse(all(top_srt));
    ++gen;
    for (pii v : top_srt) {
        if (used[v.first][v.second] != gen) {
            gen_comp(v);
            comps.emplace_back(comp);
            comp.clear();
        }
    }

//    for (auto &c : comps) {
//        cerr << "comp: ";
//        for (pii &k : c) {
//            cerr << k.first << ":" << k.second << ' ';
//        }
//        cerr << endl;
//    }

    cout << gen_dp(to_comp[0][0]) << endl;
}


//9:04

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;

#define all(x) x.begin(), x.end()
#define sz(x) (int)x.size()

#define ON

#ifdef ON
#define debug(x) cerr << #x << " = " << (x) << endl
#else
#define debug(x)
#endif

template<typename T = int>
T input() {
    T res;
    cin >> res;
    return res;
}

template<typename It>
void input_seq(It begin, It end, istream &in = cin) {
    generate(begin, end, input < typename remove_reference<decltype(*begin)>::type > );
}

template<class It>
void output(It begin, It end, ostream &out = cerr) {
    while (begin != end) {
        out << *(begin++) << ' ';
    }
    out << endl;
}

typedef pair<int, int> pii;

int n, m, d;

const int N = 100007, D = 50;
vector<int> g[N * D], ag[N * D];
char used[N * D], gen;
int top_srt[N * D], iter = 0;

int comp[N * D];
pii comps[N * D];
int comp_iter = 0, comps_iter = 0;

int to_comp[N * D];
char open[N * D];

//vector<pii> g[N][D];
//vector<pii> ag[N][D];
//char used[N][D], gen;
//vector<pii> top_srt;

//vector<vector<pii>> comps;
//vector<pii> comp;
//int to_comp[N][D];
//char open[N][D];

char comp_used[N * D];

void gen_srt(int v) {
    used[v] = gen;
    for (int u : g[v]) {
        if (used[u] != gen) {
            gen_srt(u);
        }
    }
    top_srt[iter++] = v;
}

int cur_t() {
    return clock() * 1000 / CLOCKS_PER_SEC;
}

void gen_comp(int v) {
    used[v] = gen;
    comp[comp_iter++] = v;
    to_comp[v] = comps_iter;
    for (int u : ag[v]) {
        if (used[u] == gen - 1) {
            gen_comp(u);
        }
    }
}

template <typename T>
void chkmax(T &x, T y) {
    if (x < y) {
        x = y;
    }
}

char mus_usd[N];

int gen_dp(int ind) {
    comp_used[ind] = true;
    int cnt = 0, nx = 0;
    for (int i = comps[ind].first; i < comps[ind].second; ++i) {
        int v = comp[i];
        if (open[v] && !mus_usd[v / d]) {
            mus_usd[v / d] = 1;
            ++cnt;
        }
        for (int u : g[v]) {
            if (!comp_used[to_comp[u]]) {
                chkmax(nx, gen_dp(to_comp[u]));
            }
        }
    }
    return cnt + nx;
}

signed main() {
#ifdef ON
    //    freopen("../in.txt", "r", stdin);
    //    freopen("../out.txt", "w", stdout);
#endif
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);

    n = input();
    m = input();
    d = input();

    for (int i = 0; i < m; ++i) {
        int u = input() - 1;
        int v = input() - 1;
        for (int j = 0; j < d; ++j) {
            g[d * u + j].emplace_back((d * v) + ((j + 1) % d));
            ag[(d * v) + ((j + 1) % d)].emplace_back(d * u + j);
        }
    }

    for (int i = 0; i < n; ++i) {
        string s;
        cin >> s;
        for (int j = 0; j < d; ++j) {
            open[d * i + j] = s[j] - '0';
        }
    }

    assert(cur_t() < 1200);

    ++gen;
    gen_srt(0);
    reverse(top_srt, top_srt + (D * N));
    ++gen;

    for (int v : top_srt) {
        if (used[v] == gen - 1) {
            comps[comps_iter].first = comp_iter;
            gen_comp(v);
            comps[comps_iter++].second = comp_iter;
        }
    }

//    for (auto &c : comps) {
//        cerr << "comp: ";
//        for (pii &k : c) {
//            cerr << k.first << ":" << k.second << ' ';
//        }
//        cerr << endl;
//    }

    cout << gen_dp(to_comp[0]) << endl;
}


#include <iostream>

int main() {
    std::cout << "Hello, World!" << std::endl;
    return 0;
}


//9:04

#include <bits/stdc++.h>

using namespace std;

typedef pair<int, int> pii;
typedef long long ll;
typedef long double ld;

#define all(x) x.begin(), x.end()
#define sz(x) (int)x.size()

#define ON

#ifdef ON
#define debug(x) cerr << #x << " = " << (x) << endl
#else
#define debug(x)
#endif

template<typename T = int>
T input() {
    T res;
    cin >> res;
    return res;
}

template<typename It>
void input_seq(It begin, It end, istream &in = cin) {
    generate(begin, end, input < typename remove_reference<decltype(*begin)>::type > );
}

template<class It>
void output(It begin, It end, ostream &out = cerr) {
    while (begin != end) {
        out << *(begin++) << ' ';
    }
    out << endl;
}

const int N = 100007, D = 50;
vector<pii> g[N][D];
vector<pii> ag[N][D];
char used[N][D], gen;
vector<pii> top_srt;

vector<vector<pii>> comps;
vector<pii> comp;
int to_comp[N][D];
char open[N][D];
vector<char> comp_used;

void gen_srt(pii v) {
    used[v.first][v.second] = gen;
    for (pii u : g[v.first][v.second]) {
        if (used[u.first][u.second] != gen) {
            gen_srt(u);
        }
    }
    top_srt.emplace_back(v);
}

void gen_comp(pii v) {
    used[v.first][v.second] = gen;
    comp.emplace_back(v);
    to_comp[v.first][v.second] = sz(comps);
    for (pii u : ag[v.first][v.second]) {
        if (used[u.first][u.second] != gen) {
            gen_comp(u);
        }
    }
}

template <typename T>
void chkmax(T &x, T y) {
    if (x < y) {
        x = y;
    }
}

char mus_usd[N];

int gen_dp(int ind) {
    comp_used[ind] = true;
    int cnt = 0, nx = 0;
    for (pii v : comps[ind]) {
        if (open[v.first][v.second] && !mus_usd[v.first]) {
            mus_usd[v.first] = 1;
            ++cnt;
        }
    }
    for (pii v : comps[ind]) {
        for (pii u : g[v.first][v.second]) {
            if (!comp_used[to_comp[u.first][u.second]]) {
                chkmax(nx, gen_dp(to_comp[u.first][u.second]));
            }
        }
    }
    return cnt + nx;
}

signed main() {
#ifdef ON
    //    freopen("../in.txt", "r", stdin);
    //    freopen("../out.txt", "w", stdout);
#endif
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);

    int n = input();
    int m = input();
    int d = input();

    for (int i = 0; i < m; ++i) {
        int u = input() - 1;
        int v = input() - 1;
        for (int j = 0; j < d; ++j) {
            g[u][j].emplace_back(v, (j + 1) % d);
            ag[v][(j + 1) % d].emplace_back(u, j);
        }
    }

    for (int i = 0; i < n; ++i) {
        string s;
        cin >> s;
        for (int j = 0; j < d; ++j) {
            open[i][j] = s[j] - '0';
        }
    }

    ++gen;
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < d; ++j) {
            if (used[i][j] != gen) {
                gen_srt({i, j});
            }
        }
    }
    reverse(all(top_srt));
    ++gen;
    for (pii v : top_srt) {
        if (used[v.first][v.second] != gen) {
            gen_comp(v);
            comps.emplace_back(comp);
            comp.clear();
        }
    }

    comp_used.resize(sz(comps));

//    for (auto &c : comps) {
//        cerr << "comp: ";
//        for (pii &k : c) {
//            cerr << k.first << ":" << k.second << ' ';
//        }
//        cerr << endl;
//    }

    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < d; ++j) {
            ag[i][j].clear();
        }
    }
    cout << gen_dp(to_comp[0][0]) << endl;
}


//9:04

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;

#define all(x) x.begin(), x.end()
#define sz(x) (int)x.size()

#define ON

#ifdef ON
#define debug(x) cerr << #x << " = " << (x) << endl
#else
#define debug(x)
#endif

template<typename T = int>
T input() {
    T res;
    cin >> res;
    return res;
}

template<typename It>
void input_seq(It begin, It end, istream &in = cin) {
    generate(begin, end, input < typename remove_reference<decltype(*begin)>::type > );
}

template<class It>
void output(It begin, It end, ostream &out = cerr) {
    while (begin != end) {
        out << *(begin++) << ' ';
    }
    out << endl;
}

typedef pair<int, int> pii;

int n, m, d;

const int N = 100007, D = 50;
vector<int> g[N * D], ag[N * D];
char used[N * D], gen;
int top_srt[N * D], iter = 0;

vector<int> comps[N * D];
int comp_iter = 0;
vector<int> comp;

int to_comp[N * D];
char open[N * D];

//vector<pii> g[N][D];
//vector<pii> ag[N][D];
//char used[N][D], gen;
//vector<pii> top_srt;

//vector<vector<pii>> comps;
//vector<pii> comp;
//int to_comp[N][D];
//char open[N][D];

char comp_used[N * D];

void gen_srt(int v) {
    used[v] = gen;
    for (int u : g[v]) {
        if (used[u] != gen) {
            gen_srt(u);
        }
    }
    top_srt[iter++] = v;
}

void gen_comp(int v) {
    used[v] = gen;
    comp.emplace_back(v);
    to_comp[v] = comp_iter;
    for (int u : ag[v]) {
        if (used[u] == gen - 1) {
            gen_comp(u);
        }
    }
}

template <typename T>
void chkmax(T &x, T y) {
    if (x < y) {
        x = y;
    }
}

char mus_usd[N];

int gen_dp(int ind) {
    comp_used[ind] = true;
    int cnt = 0, nx = 0;
    for (int v : comps[ind]) {
        if (open[v] && !mus_usd[v / d]) {
            mus_usd[v / d] = 1;
            ++cnt;
        }
        for (int u : g[v]) {
            if (!comp_used[to_comp[u]]) {
                chkmax(nx, gen_dp(to_comp[u]));
            }
        }
    }
    return cnt + nx;
}

signed main() {
#ifdef ON
    //    freopen("../in.txt", "r", stdin);
    //    freopen("../out.txt", "w", stdout);
#endif
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);

    n = input();
    m = input();
    d = input();

    for (int i = 0; i < m; ++i) {
        int u = input() - 1;
        int v = input() - 1;
        for (int j = 0; j < d; ++j) {
            g[d * u + j].emplace_back((d * v) + ((j + 1) % d));
            ag[(d * v) + ((j + 1) % d)].emplace_back(d * u + j);
        }
    }

    for (int i = 0; i < n; ++i) {
        string s;
        cin >> s;
        for (int j = 0; j < d; ++j) {
            open[d * i + j] = s[j] - '0';
        }
    }

    ++gen;
    gen_srt(0);
    reverse(top_srt, top_srt + (D * N));
    ++gen;
    for (int v : top_srt) {
        if (used[v] == gen - 1) {
            gen_comp(v);
            comps[comp_iter++] = move(comp);
            comp.clear();
        }
    }

//    for (auto &c : comps) {
//        cerr << "comp: ";
//        for (pii &k : c) {
//            cerr << k.first << ":" << k.second << ' ';
//        }
//        cerr << endl;
//    }

    cout << gen_dp(to_comp[0]) << endl;
}


//9:04

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;

#define all(x) x.begin(), x.end()
#define sz(x) (int)x.size()

#define ON

#ifdef ON
#define debug(x) cerr << #x << " = " << (x) << endl
#else
#define debug(x)
#endif

template<typename T = int>
T input() {
    T res;
    cin >> res;
    return res;
}

template<typename It>
void input_seq(It begin, It end, istream &in = cin) {
    generate(begin, end, input < typename remove_reference<decltype(*begin)>::type > );
}

template<class It>
void output(It begin, It end, ostream &out = cerr) {
    while (begin != end) {
        out << *(begin++) << ' ';
    }
    out << endl;
}

typedef pair<int, int> pii;

int n, m, d;

const int N = 100007, D = 51;
vector<int> g[N], ag[N];
//vector<int> kekg[N], kekag[N];
char used[N * D], gen;
int top_srt[N * D], iter = 0;

int comp[N * D];
pii comps[N * D];
int comp_iter = 0, comps_iter = 0;

int to_comp[N * D];
bool open[N * D];

//vector<pii> g[N][D];
//vector<pii> ag[N][D];
//char used[N][D], gen;
//vector<pii> top_srt;

//vector<vector<pii>> comps;
//vector<pii> comp;
//int to_comp[N][D];
//char open[N][D];

bool comp_used[N * D];

void gen_srt(int v) {
    int vv = v / d, day = v % d;
    used[v] = gen;
    for (int uu : g[vv]) {
        int u = d * uu + ((day + 1) % d);
        if (used[u] != gen) {
            gen_srt(u);
        }
    }
    top_srt[iter++] = v;
}

int cur_t() {
    return clock() * 1000 / CLOCKS_PER_SEC;
}

void gen_comp(int v) {
    used[v] = gen;
    comp[comp_iter++] = v;
    to_comp[v] = comps_iter;
    int vv = v / d, day = v % d;
    for (int uu : ag[vv]) {
        int u = d * uu + ((day - 1 + d) % d);
        if (used[u] == gen - 1) {
            gen_comp(u);
        }
    }
}

template <typename T>
void chkmax(T &x, T y) {
    if (x < y) {
        x = y;
    }
}

bool mus_usd[N];

int gen_dp(int ind) {
    comp_used[ind] = true;
    int cnt = 0, nx = 0;
    for (int i = comps[ind].first; i < comps[ind].second; ++i) {
        int v = comp[i];
        int vv = v / d, day = v % d;
        if (open[v] && !mus_usd[vv]) {
            mus_usd[vv] = true;
            ++cnt;
        }
        for (int uu : g[vv]) {
            int u = d * uu + ((day + 1) % d);
            if (!comp_used[to_comp[u]]) {
                chkmax(nx, gen_dp(to_comp[u]));
            }
        }
    }
    return cnt + nx;
}

signed main() {
#ifdef ON
    //    freopen("../in.txt", "r", stdin);
    //    freopen("../out.txt", "w", stdout);
#endif
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);

    n = input();
    m = input();
    d = input();

    assert(n < N);
    assert(m < N);
    assert(d < D);

    for (int i = 0; i < m; ++i) {
        int u = input() - 1;
        int v = input() - 1;
        g[u].emplace_back(v);
        ag[v].emplace_back(u);

//        for (int j = 0; j < d; ++j) {
//            kekg[d * u + j].push_back((d * v) + ((j + 1) % d));
//            kekag[(d * v) + ((j + 1) % d)].push_back(d * u + j);
//        }
    }

//    assert(cur_t() < 1200);

    for (int i = 0; i < n; ++i) {
        string s;
        cin >> s;
        for (int j = 0; j < d; ++j) {
            open[d * i + j] = s[j] - '0';
        }
    }

    ++gen;
    gen_srt(0);
    reverse(top_srt, top_srt + (D * N));
    ++gen;

    for (int v : top_srt) {
        if (used[v] == gen - 1) {
            comps[comps_iter].first = comp_iter;
            gen_comp(v);
            comps[comps_iter++].second = comp_iter;
        }
    }

//    for (auto &c : comps) {
//        cerr << "comp: ";
//        for (pii &k : c) {
//            cerr << k.first << ":" << k.second << ' ';
//        }
//        cerr << endl;
//    }

    cout << gen_dp(to_comp[0]) << endl;
}


//9:04

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;

#define all(x) x.begin(), x.end()
#define sz(x) (int)x.size()

#define ON

#ifdef ON
#define debug(x) cerr << #x << " = " << (x) << endl
#else
#define debug(x)
#endif

template<typename T = int>
T input() {
    T res;
    cin >> res;
    return res;
}

template<typename It>
void input_seq(It begin, It end, istream &in = cin) {
    generate(begin, end, input < typename remove_reference<decltype(*begin)>::type > );
}

template<class It>
void output(It begin, It end, ostream &out = cerr) {
    while (begin != end) {
        out << *(begin++) << ' ';
    }
    out << endl;
}

typedef pair<int, int> pii;

int n, m, d;

const int N = 100007, D = 51;
vector<int> g[N], ag[N];
char used[N * D], gen;
int top_srt[N * D], iter = 0;

int comp[N * D];
pii comps[N * D];
int comp_iter = 0, comps_iter = 0;

int to_comp[N * D];
bool open[N * D];

//vector<pii> g[N][D];
//vector<pii> ag[N][D];
//char used[N][D], gen;
//vector<pii> top_srt;

//vector<vector<pii>> comps;
//vector<pii> comp;
//int to_comp[N][D];
//char open[N][D];

bool comp_used[N * D];

void gen_srt(int v) {
    int vv = v / d, day = v % d;
    assert(vv < N);
    used[v] = gen;
    for (int uu : g[vv]) {
        int u = d * uu + ((day + 1) % d);
        if (used[u] != gen) {
            gen_srt(u);
        }
    }
    top_srt[iter++] = v;
}

int cur_t() {
    return clock() * 1000 / CLOCKS_PER_SEC;
}

void gen_comp(int v) {
    used[v] = gen;
    comp[comp_iter++] = v;
    to_comp[v] = comps_iter;
    int vv = v / d, day = v % d;
    for (int uu : ag[vv]) {
        int u = d * uu + ((day - 1 + d) % d);
        if (used[u] == gen - 1) {
            gen_comp(u);
        }
    }
}

template <typename T>
void chkmax(T &x, T y) {
    if (x < y) {
        x = y;
    }
}

bool mus_usd[N];

int gen_dp(int ind) {
    comp_used[ind] = true;
    int cnt = 0, nx = 0;
    for (int i = comps[ind].first; i < comps[ind].second; ++i) {
        int v = comp[i];
        int vv = v / d, day = v % d;
        if (open[v] && !mus_usd[vv]) {
            mus_usd[vv] = true;
            ++cnt;
        }
        for (int uu : g[vv]) {
            int u = d * uu + ((day + 1) % d);
            if (!comp_used[to_comp[u]]) {
                chkmax(nx, gen_dp(to_comp[u]));
            }
        }
    }
    return cnt + nx;
}

signed main() {
#ifdef ON
    //    freopen("../in.txt", "r", stdin);
    //    freopen("../out.txt", "w", stdout);
#endif
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);

    n = input();
    m = input();
    d = input();

    assert(n < N);
    assert(m < N);
    assert(d < D);

    for (int i = 0; i < m; ++i) {
        int u = input() - 1;
        int v = input() - 1;
        assert(u < N);
        assert(v < N);
        g[u].emplace_back(v);
        ag[v].emplace_back(u);
    }

//    assert(cur_t() < 1200);

    for (int i = 0; i < n; ++i) {
        string s;
        cin >> s;
        for (int j = 0; j < d; ++j) {
            open[d * i + j] = s[j] - '0';
        }
    }

    ++gen;
    gen_srt(0);
    reverse(top_srt, top_srt + (D * N));
    ++gen;

    for (int v : top_srt) {
        if (used[v] == gen - 1) {
            comps[comps_iter].first = comp_iter;
            gen_comp(v);
            comps[comps_iter++].second = comp_iter;
        }
    }

//    for (auto &c : comps) {
//        cerr << "comp: ";
//        for (pii &k : c) {
//            cerr << k.first << ":" << k.second << ' ';
//        }
//        cerr << endl;
//    }

    cout << gen_dp(to_comp[0]) << endl;
}