zoukankan      html  css  js  c++  java
  • 旅行路线

    旅行路线

    时间限制: 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 君想知道共有多少种不同的旅行路线,相似的若干条旅行路线只算做一种。

    输入

    第一行一个整数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
    ",ret);
        return 0;
    }
  • 相关阅读:
    在有跳板机的情况下,SecureCRT自动连接到目标服务器
    JavaScript中使用console调试程序的坑
    Python中docstring文档的写法
    Nginx+uWSGI+Django原理
    uWSGI uwsgi_response_write_body_do(): Connection reset by peer 报错的解决方法
    Python LOGGING使用方法
    Python计算斗牛游戏的概率
    Python垃圾回收机制详解
    PhantomJS实现最简单的模拟登录方案
    如何设置Jquery UI Menu 菜单为横向展示
  • 原文地址:https://www.cnblogs.com/dyzll/p/7623406.html
Copyright © 2011-2022 走看看