首页 > 其他分享 >[bzoj 1471] 不相交路径 (容斥原理)

[bzoj 1471] 不相交路径 (容斥原理)

时间:2023-02-21 10:04:27浏览次数:55  
标签:fir int d% 容斥 ++ 1471 MAXN id bzoj


题目描述

给出一个结点的有向无环简单图。给出[bzoj 1471] 不相交路径 (容斥原理)_拓扑排序个不同的点[bzoj 1471] 不相交路径 (容斥原理)_c++_02[bzoj 1471] 不相交路径 (容斥原理)_拓扑排序_03[bzoj 1471] 不相交路径 (容斥原理)_c++_04[bzoj 1471] 不相交路径 (容斥原理)_拓扑排序_05,定义不相交路径为两条路径,两条路径的起点分别为[bzoj 1471] 不相交路径 (容斥原理)_c++_02[bzoj 1471] 不相交路径 (容斥原理)_c++_04,对应的两条路径的终点为[bzoj 1471] 不相交路径 (容斥原理)_拓扑排序_03[bzoj 1471] 不相交路径 (容斥原理)_拓扑排序_05,要求满足这两条路径不相交,即两条路径上没有公共的点。 现在要求不相交路径的方案数。

题目分析

这道题类似于​​[bzoj 4767] 两双手​​​ 记[bzoj 1471] 不相交路径 (容斥原理)_拓扑排序_10表示从[bzoj 1471] 不相交路径 (容斥原理)_拓扑排序_11走到[bzoj 1471] 不相交路径 (容斥原理)_拓扑排序_12路径条数
[bzoj 1471] 不相交路径 (容斥原理)_c++_13表示两个点从[bzoj 1471] 不相交路径 (容斥原理)_c++_14开始走第一次相遇在i点的方案数
根据容斥常识,则有:

求最终答案也容斥一下:
[bzoj 1471] 不相交路径 (容斥原理)_拓扑排序_15
所以[bzoj 1471] 不相交路径 (容斥原理)_#include_16预处理[bzoj 1471] 不相交路径 (容斥原理)_拓扑排序_17
所以[bzoj 1471] 不相交路径 (容斥原理)_#include_18求出[bzoj 1471] 不相交路径 (容斥原理)_拓扑排序_19
所以[bzoj 1471] 不相交路径 (容斥原理)_拓扑排序_20求出[bzoj 1471] 不相交路径 (容斥原理)_拓扑排序_21
时间复杂度[bzoj 1471] 不相交路径 (容斥原理)_#include_16

upd:法2:高论

  • 考虑这两个位置第⼀次相交在u,那么可以a->u->c, b->u->d变成 b->u->c, a->u->d。
    所以答案为dp[a][c]*dp[b][d]-dp[b][c]*dp[a][d]

类似LGV Lemma 但是并不满足“一定相交”条件,这里的正确性是两条路径的特殊性导致的。

AC code

法1:100ms

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 155;
int n, m, d[MAXN], fir[MAXN], to[MAXN*MAXN], nxt[MAXN*MAXN], cnt;
inline void Add(int u, int v) { to[++cnt] = v, nxt[cnt] = fir[u], fir[u] = cnt, ++d[v]; }
int topo[MAXN], id[MAXN], cur, q[MAXN], s, t; //topo为拓扑序,id为topo的反函数
long long f[MAXN][MAXN], g[MAXN];
int main ()
{
scanf("%d%d", &n, &m);
for(int i = 1, x, y; i <= m; ++i)
scanf("%d%d", &x, &y), Add(x, y);
for(int i = 1; i <= n; ++i) if(!d[i]) q[t++] = i;
while(s < t) //拓扑排序
{
int u = q[s++]; id[topo[u] = ++cur] = u;
for(int i = fir[u]; i; i = nxt[i])
if(--d[to[i]] == 0) q[t++] = to[i];
}
for(int i = 1, u; i <= n; ++i)
{
u = id[i]; f[u][u] = 1;
for(int j = i, v; j <= n; ++j)
{
v = id[j];
for(int k = fir[v]; k; k = nxt[k]) f[u][to[k]] += f[u][v];
}
}
int a, b, c, d;
scanf("%d%d%d%d", &a, &b, &c, &d);
for(int i = 1, u; i <= n; ++i)
{
u = id[i];
g[u] = f[a][u] * f[c][u];
for(int j = 1, v; j < i; ++j)
{
v = id[j];
g[u] -= g[v] * f[v][u] * f[v][u];
}
}
long long ans = f[a][b] * f[c][d];
for(int i = 1, u; i <= n; ++i)
{
u = id[i];
ans -= g[u] * f[u][b] * f[u][d];
}
printf("%lld\n", ans);
}

法2:80ms

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 155;
int n, m, d[MAXN], fir[MAXN], to[MAXN*MAXN], nxt[MAXN*MAXN], cnt;
inline void Add(int u, int v) { to[++cnt] = v, nxt[cnt] = fir[u], fir[u] = cnt, ++d[v]; }
int topo[MAXN], id[MAXN], cur, q[MAXN], s, t; //topo为拓扑序,id为topo的反函数
long long f[MAXN][MAXN];
int main ()
{
scanf("%d%d", &n, &m);
for(int i = 1, x, y; i <= m; ++i)
scanf("%d%d", &x, &y), Add(x, y);
for(int i = 1; i <= n; ++i) if(!d[i]) q[t++] = i;
while(s < t) //拓扑排序
{
int u = q[s++]; id[topo[u] = ++cur] = u;
for(int i = fir[u]; i; i = nxt[i])
if(--d[to[i]] == 0) q[t++] = to[i];
}
for(int i = 1, u; i <= n; ++i)
{
u = id[i]; f[u][u] = 1;
for(int j = i, v; j <= n; ++j)
{
v = id[j];
for(int k = fir[v]; k; k = nxt[k]) f[u][to[k]] += f[u][v];
}
}
int a, b, c, d;
scanf("%d%d%d%d", &a, &b, &c, &d);
long long ans = f[a][b] * f[c][d] - f[c][b] * f[a][d];
printf("%lld\n", ans);
}


标签:fir,int,d%,容斥,++,1471,MAXN,id,bzoj
From: https://blog.51cto.com/u_15973510/6075829

相关文章

  • [Sdoi2013] [bzoj 3198] spring (hash+容斥原理)
    题目描述给出个维坐标,求有多少对点对满足恰好个位置相等坐标数值在以内题目分析这道题一看就是hash容斥原理,用个位置对应相等个位置对应相等个位置对应相等的…但是不能......
  • [bzoj 3701] Olympic Games (莫比乌斯反演)
    题目描述给出表示一个的格点图,求能够互相看见的点对个数对取模的值.能互相看见定义为此两点连线上没有其他的格点且欧氏距离在[l,r]范围内题目分析首先我们将上下左右相邻......
  • [bzoj 2393] Cirno的完美算数教室 (容斥原理+dfs剪枝)
    题目描述发现了一种数,这种数呢只含有和两种数字现在想知道中有多少个数能被数整除  1<L<R<10^{10}题目分析由于R<10^{10},最大只有10位的数可以对答案造成贡献,每一位只能......
  • agc061_c 容斥+dp
    题意有两个长度为\(n\)的严格递增序列\(A_i,B_i\),满足\(\foralli\len,A_i<B_i\),且\(A_i\)和\(B_i\)的所有元素恰好取遍\(1-2n\)。现在有一个队列,对于\(1\)......
  • 浅析排列组合、斯特林数、贝尔数、二项式定理与推论及其反演、子集反演、广义容斥
    浅析排列组合、斯特林数、贝尔数、二项式定理与推论及其反演、子集反演、广义容斥目录浅析排列组合、斯特林数、贝尔数、二项式定理与推论及其反演、子集反演、广义容斥更......
  • 【Baltic2003】【BZOJ1370】Gang团伙(并查集,拆点)
    problem给定n个人朋友的朋友是朋友,敌人的敌人是朋友朋友之间组成一个团伙,求团伙数solution将每个点x拆成两个:x和x+n(分别表示x的朋友和敌人)如果x和y是朋友,就将x和y合并如果x......
  • 【bzoj4668】冷战 (并查集按秩合并+朴素LCA)
    题目描述1946年3月5日,英国前首相温斯顿·丘吉尔在美国富尔顿发表“铁幕演说”,正式拉开了冷战序幕。美国和苏联同为世界上的“超级大国”,为了争夺世界霸权,两国及其盟国......
  • BZOJ-2301-[HAOI2011]Problem b(莫比乌斯反演+容斥)
    [HAOI2011]Problemb描述对于给出的n个询问,每次求有多少个数对(x,y),满足a≤x≤b,c≤y≤d,且gcd(x,y)=k,gcd(x,y)函数为x和y的最大公约数。Input 第一行一个整数n,接下来n......
  • BZOJ3786 星系探索
    写了发假的\(\text{ETT}\),\(\text{FQH-Treap}\)维护括号序\(\text{Code}\)#include<bits/stdc++.h>#defineINinline#defineebemplace_backusingnamespacestd......
  • BZOJ3262 陌上花开(cdq分治模板)
    Description有n朵花,每朵花有三个属性:花形(s)、颜色(c)、气味(m),用三个整数表示。现在要对每朵花评级,一朵花的级别是它拥有的美丽能超过的花的数量。定义一朵花A比另一朵......