zoukankan      html  css  js  c++  java
  • 【BZOJ1471】不相交路径 题解(拓扑排序+动态规划+容斥原理)

    题目描述

    在有向无环图上给你两个起点和终点分别为$a,b,c,d$。问有几种路径方案使得能从$a$走到$b$的同时能从$c$走到$d$,且两个路径没有交点。

    $1leq nleq 200,1leq mleq 5000$。

    --------------------------------------------------------------------

    经过了深刻地思考,你会发现,由于这是一个$DAG$图,我们可以将其转化为动态规划来做,同时我们先要将图建立成一个拓扑图。

    然后你又经过了深刻地思考,你会发现这道题还需要容斥原理。

    假设$g[i]$是从$a_{1}$和$b_{1}$到共同点i的路径总方案数,则可以得

    $g[i]=f[a_{1}][i]*f[b_{1}][i]-sum_{k=1}^{i-1} g[k]*f[k][i]^2$

    则可以得

    $ans=f[a_{1}][b_{1}]*f[a_{2}][b_{2}]-sum_{k=1}^{n} g[k]*f[k][a_{2}]*f[k][b_{2}]$

    由于数据范围较小,知道了思路是个OIer都有方法将其实现,不存在卡时间的问题。

    #include<bits/stdc++.h>
    #define int unsigned long long
    using namespace std;
    const int maxn=205;
    struct node
    {
        int next,to;
    }edge[200005];
    int head[200005];
    int g[maxn],f[maxn][maxn],in[maxn],pos[maxn];
    int n,m,u,v,a,b,c,d,cnt,tot,ans;
    queue<int> q;
    void add(int from,int to)
    {
        edge[++tot].next=head[from];
        edge[tot].to=to;
        head[from]=tot;
        in[to]++;
    }
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
        while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    signed main()
    {
        n=read(),m=read();
        for (int i=1;i<=m;i++)
        {
            u=read(),v=read();
            add(u,v);
        }
        a=read(),b=read(),c=read(),d=read();
        for (int i=1;i<=n;i++) if (!in[i]) q.push(i);
        while(!q.empty())
        {
            int now=q.front();q.pop();
            pos[++cnt]=now;
            for (int i=head[now];i;i=edge[i].next)
            {
                int to=edge[i].to;
                in[to]--;
                if (!in[to]) q.push(to);
            }
        }
        for (int i=1;i<=n;i++)
        {
            u=pos[i];f[u][u]=1;
            for (int j=i;j<=n;j++)
            {
                v=pos[j];
                for (int k=head[v];k;k=edge[k].next){
                    int to=edge[k].to;
                    f[u][to]+=f[u][v];
                }
            }
        }
        for (int i=1;i<=n;i++)
        {
            u=pos[i];
            g[u]=f[a][u]*f[c][u];
            for (int j=1;j<i;j++)
            {
                v=pos[j];
                g[u]-=g[v]*f[v][u]*f[v][u];
            }
        }
        ans=f[a][b]*f[c][d];
        for (int i=1;i<=n;i++) u=pos[i],ans-=g[u]*f[u][b]*f[u][d];
        printf("%lld",ans);
        return 0;
    }
  • 相关阅读:
    jQuery里使用setinterval
    关于java以及JavaScript或者更多的语言中Data类的问题
    重置input checked
    利用CSS变量实现悬浮效果
    vue 可编辑表格组件
    js 可拉伸表格
    vue 自定义拖拽指令
    vue 表格导出excel
    vue 侧边导航栏递归显示
    RUP(Rational Unified Process)统一软件过程概述
  • 原文地址:https://www.cnblogs.com/Invictus-Ocean/p/12469700.html
Copyright © 2011-2022 走看看