旅行路线
Posted mxzf0213
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了旅行路线相关的知识,希望对你有一定的参考价值。
旅行路线
时间限制: 1 Sec 内存限制: 128 MB题目描述
A 君准备在 Z 国进行一次旅行。Z 国中有 n 个城市,城市从1到 n 进行编号,其中1号城市为 Z 国首都。Z 国的旅行交通网由 n−1条单向道路构成,并且从任何一个城市出发都可以通过旅行网到达首都。
一条旅行交通网中的旅行路线,可以用路线上所经过的城市来描述,如 {v1,v2,...,vm},它表示一条经过了m个城市的旅行路线,且城市 vi到城市 vi+1有一条单向道路相连。
若两个城市所连接的道路数量相同,则 A 君会认为这两座城市是相似的。
对于两条路线 {u1,u2,...,up}与 {v1,v2,...,vq},若 p=q且 ∀1≤i≤p,城市 ui与 vi是相似的,则 A 君认为这两条旅行路线也是相似的。 现在 A 君想知道共有多少种不同的旅行路线,相似的若干条旅行路线只算做一种。
一条旅行交通网中的旅行路线,可以用路线上所经过的城市来描述,如 {v1,v2,...,vm},它表示一条经过了m个城市的旅行路线,且城市 vi到城市 vi+1有一条单向道路相连。
若两个城市所连接的道路数量相同,则 A 君会认为这两座城市是相似的。
对于两条路线 {u1,u2,...,up}与 {v1,v2,...,vq},若 p=q且 ∀1≤i≤p,城市 ui与 vi是相似的,则 A 君认为这两条旅行路线也是相似的。 现在 A 君想知道共有多少种不同的旅行路线,相似的若干条旅行路线只算做一种。
输入
第一行一个整数n表示 Z 国城市个数。 接下来n−1行每行两个整数 x,y,表示一条从x到y的单向道路。(1≤n≤105)
输出
仅一行一个整数表示答案。
样例输入
3
2 1
3 1
样例输出
3
分析:在树上建立后缀自动机求不同子串个数;
因为树是以1为根的有向树,直接以1为根dfs即可;
每个点度数不定,注意儿子节点需要动态开;
代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <algorithm> #include <climits> #include <cstring> #include <string> #include <set> #include <bitset> #include <map> #include <queue> #include <stack> #include <vector> #include <cassert> #include <ctime> #define rep(i,m,n) for(i=m;i<=(int)n;i++) #define inf 0x3f3f3f3f #define mod 1000000007 #define vi vector<int> #define pb push_back #define mp make_pair #define fi first #define se second #define ll long long #define pi acos(-1.0) #define pii pair<int,int> #define sys system("pause") #define ls (rt<<1) #define rs (rt<<1|1) #define all(x) x.begin(),x.end() const int maxn=2e5+10; const int N=5e4+10; using namespace std; ll gcd(ll p,ll q){return q==0?p:gcd(q,p%q);} ll qmul(ll p,ll q,ll mo){ll f=0;while(q){if(q&1)f=(f+p)%mo;p=(p+p)%mo;q>>=1;}return f;} ll qpow(ll p,ll q){ll f=1;while(q){if(q&1)f=f*p;p=p*p;q>>=1;}return f;} int n,m,k,t; struct samnode{ map<int,int>son; int f,l; }sam[maxn]; int cnt,root,last; void init(){ root = last = cnt = 1; } void add(int x,int last) { int cur = ++cnt; sam[cur].l = sam[last].l + 1; int p; for (p=last; p && !sam[p].son.count(x); p=sam[p].f) sam[p].son[x] = cur; if (!p) sam[cur].f = root; else { int q = sam[p].son[x]; if (sam[p].l + 1 == sam[q].l)sam[cur].f = q; else { int clone = ++cnt; sam[clone]=sam[q]; sam[clone].l = sam[p].l + 1; sam[q].f = sam[cur].f = clone; for (; p!=-1 && sam[p].son.count(x)&&sam[p].son[x]==q; p=sam[p].f) sam[p].son[x] = clone; } } last = cur; } vi e[maxn]; int du[maxn]; void dfs(int x,int rt) { int i; add(du[x],rt); rt=sam[rt].son[du[x]]; rep(i,0,e[x].size()-1) { dfs(e[x][i],rt); } } int main(){ int i,j; init(); scanf("%d",&n); rep(i,1,n-1) { int x,y; scanf("%d%d",&x,&y); e[y].pb(x); du[x]++,du[y]++; } dfs(1,1); ll ret=0; rep(i,1,cnt)ret+=sam[i].l-sam[sam[i].f].l; printf("%lld\n",ret); return 0; }
以上是关于旅行路线的主要内容,如果未能解决你的问题,请参考以下文章