#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 1e5 + 5, mod = 998244353;
struct Node{
int v, w;
};
vector<Node> G[maxn];
vector<int> g[maxn];
int ind[maxn];
int c0[maxn];//c0[u]表示从u到尽头 0的个数
int c1[maxn];//c1[u]表示从u到尽头 1的个数
int c10[maxn];//c10[u]表示从u到尽头 1,0逆序对的个数
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
queue<int> q;
int n, i, j;
cin >> n;
for(i = 1; i <= n; i++){
cin >> ind[i];
for(j = 1; j <= ind[i]; j++){
int v, w;
cin >> v >> w;
G[i].push_back({v, w});
g[v].push_back(i);
}
if(!ind[i]) q.push(i);
}
while(!q.empty()){
int u = q.front();
q.pop();
for(auto v : g[u]){
ind[v]--;
if(!ind[v]) q.push(v);
}
for(auto x : G[u]){
int v = x.v;
int w = x.w;
//考虑当前边
if(w == 1) c10[u] = (c10[u] + c0[v]) % mod;//如果当前边是1,就加上后面0的个数
else c10[u] = (c10[u] + c1[u]) % mod;//当前是0,就加上前面1的个数
//不考虑当前边
c10[u] = (c10[u] + c1[u] * c0[v]) % mod;//前面1和后面0自由组合
c10[u] = (c10[u] + c10[v]) % mod;//加上子结点逆序对个数
c1[u] = (c1[u] + c1[v] + (w == 1)) % mod;
c0[u] = (c0[u] + c0[v] + (w == 0)) % mod;
}
}
cout << c10[1];
return 0;
}
树形dp求逆序对
最新推荐文章于 2025-12-13 19:26:52 发布
这篇文章描述了一个使用C++编写的程序,解决了一个与图相关的问题,计算从起点到终点的1-0逆序对的数量。程序利用队列和动态规划的方法来递归地更新节点的c0、c1和c10计数。
1106

被折叠的 条评论
为什么被折叠?



