首页 > 其他分享 >P7531 [USACO21OPEN] Routing Schemes P 题解

P7531 [USACO21OPEN] Routing Schemes P 题解

时间:2024-12-18 17:10:36浏览次数:3  
标签:源点 int 题解 USACO21OPEN P7531 ++ 110 res cu

best 定理居然还有运用范围。

思路

考虑如何来判断是否有解。

由于每一条边都需要用到。

但是它是使用很多条路径进行覆盖。

我们考虑一个很巧妙的转化。

建立一个超级源点,源点向每一条路径的开头连一条边。每一条路径的结尾向源点连一条边,这样一条路径就变成了一个回路。

把所有回路连起来,就是一条欧拉回路。

问题转化成了欧拉回路计数。

对于欧拉回路计数,我们有经典的 best 定理。

它描述的是这样一个东西。

\[ans=内向树个数\times \prod (deg_i-1)! \]

内向树个数容易使用矩阵树定理求出。

考虑这个题实际求的是匹配路径方案数。

所以要把源点的 \((deg_i-1)!\) 除掉。

时间复杂度:\(O(Tn^3)\)。

Code

#include <bits/stdc++.h>
using namespace std;

const int mod = 1e9 + 7;

int n, k, ru[110], cu[110];
int f[110];
int a[110][110];

inline int power(int x, int y) {
  int res = 1;
  while (y) {
    if (y & 1) res = 1ll * res * x % mod;
    x = 1ll * x * x % mod, y >>= 1;
  }
  return res;
}
inline int gauss() {
  int res = 1;
  for (int i = 1; i <= n; i++)
    for (int j = 1; j <= n; j++)
      if (a[i][j] < 0) a[i][j] += mod;
  for (int i = 1; i <= n; i++) {
    if (ru[i] == 0 && cu[i] == 0) continue;
    int id = i;
    for (int j = i; j <= n; j++) if (a[j][i]) id = j;
    if (id != i) {
      swap(a[i], a[id]), res = mod - res;
    }
    int p = power(a[i][i], mod - 2);
    for (int j = i + 1; j <= n; j++) {
      int c = 1ll * a[j][i] * p % mod;
      for (int k = i; k <= n; k++) {
        a[j][k] = (a[j][k] - 1ll * a[i][k] * c) % mod;
        if (a[j][k] < 0) a[j][k] += mod;
      }
    }
  }
  for (int i = 1; i <= n; i++)
    if (ru[i] || cu[i]) res = 1ll * res * a[i][i] % mod;
  return res;
}
inline void solve() {
  cin >> n >> k;
  for (int i = 1; i <= n; i++) {
    char c;
    cin >> c;
    if (c == 'S') a[0][i]--, a[0][0]++, cu[0]++, ru[i]++;
    if (c == 'R') a[i][0]--, a[i][i]++, cu[i]++, ru[0]++;
  }
  for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= n; j++) {
      char c;
      cin >> c;
      if (c == '1') {
        a[i][j]--;
        a[i][i]++;
        cu[i]++, ru[j]++;
      }
    }
  }
  bool flag = 0;
  for (int i = 0; i <= n; i++)
    if (ru[i] != cu[i]) flag = 1;
  if (flag == 0) {
    int ns = gauss();
    for (int i = 1; i <= n; i++)
      if (cu[i]) ns = 1ll * ns * f[cu[i] - 1] % mod;
    cout << ns << "\n";
  } else {
    cout << 0 << "\n";
  }
  memset(a, 0, sizeof a);
  memset(ru, 0, sizeof ru);
  memset(cu, 0, sizeof cu);
}

int main() {
  int t;
  cin >> t;
  f[0] = 1;
  for (int i = 1; i <= 100; i++) f[i] = 1ll * f[i - 1] * i % mod;
  while (t--) solve();
}

标签:源点,int,题解,USACO21OPEN,P7531,++,110,res,cu
From: https://www.cnblogs.com/JiaY19/p/18615392

相关文章

  • AT_abc129_f [ABC129F] Takahashi's Basics in Education and Learning 题解
    题目传送门前置知识矩阵加速递推解法设\(f_{i}\)表示将\(s_{1}\sims_{i}\)拼起来后的值,状态转移方程形如\(f_{i}=10^{k}f_{i-1}+s_{i}\),其中\(k=\left\lfloor\log_{10}s_{i}\right\rfloor+1\)。又因为保证等差数列中的元素\(\le10^{18}\),对于每个\(k\in[1,......
  • Pinely Round 2 (Div. 1 + Div. 2) / Codeforces contest 1863 题解
    ProblemA.Channelhttps://codeforces.com/contest/1863/problem/A流程看起来很复杂,让我们重述一下题意。两数\(x\),\(y\)。\(opt1\),你可以选\(x\)和\(y\)当中某个非零的,减少\(1\)。\(opt2\),让\(x\)增加\(1\)。\(Q1:\)是否可以让\(y\)变成\(0\),$Q2:$......
  • AT_agc032_d [AGC032D] Rotation Sort 题解
    考虑确定哪些点不动,这些点一定构成一个单调递增子序列,那么对于剩下的点:若在它之前存在一个不动点大于它,则需要花费\(b\)的代价向前移动。若在它之后存在一个不动点小于它,则需要花费\(a\)的代价向后移动。如果两个都不存在,则它一定可以加入不动点序列。考虑dp,记\(f_{i,......
  • 鸿蒙Flutter环境相关问题解决方法
    鸿蒙Flutter环境相关问题建议使用的开发工具版本flutter3.7.12-ohos版本python3.8-python3.11java17node18ohpm1.6+HamonyOSSDKapi11Xcode14.3断网环境flutterpubget执行失败解决方案:加上--offline参数,完整命令flutterpubget--offlinemac环境releas......
  • Hongcow Builds A Nation 题解
    HongcowBuildsANation题解洛谷。Codeforces。题目描述给定一张\(n\)个点,\(m\)条边的无向图,有\(k\)个点是特殊点。每个连通块中都得保证无重边、无自环,且最多只有一个特殊点。求最多还能加多少条边,满足以上条件。思路简述首先考虑以下有\(n\)个点的完全图共有多......
  • P6803 [CEOI2020] 星际迷航 题解
    \(\text{P6803[CEOI2020]星际迷航题解}\)观察这个从第\(0\)棵树走向第\(D\)棵树的过程是困难的,我们难以判定走到下一棵树的情况。于是我们不妨从第\(D\)棵树向第\(0\)棵树来倒推。从第\(i\)层走向第\(i+1\)层的边为\(x\toy\)时,事实上此时\(y\)就是第\(i+1\)......
  • CF335F 题解
    \(CF335F\)\(Buy\)\(One\),\(Get\)\(One\)\(Free\)考虑可撤销贪心+小根堆维护。首先价格相同的馅饼可以放到一起考虑,从大到小排序后考虑每种不同价格的馅饼。则第\(i\)种最多白嫖的个数为\(p=\min(c_i,num-2*sum)\),其中\(c_i\)为馅饼个数,\(num\)为已经考虑的更贵的......
  • 7 Oracle 经典面试题解析
    PL/SQL面试题--1、创建序列seq_employee,该序列每次取的时候自动增加,从1开始计数,不设最大值,并且一直累加,不循环;CREATESEQUENCEseq_employeeSTARTWITH1INCREMENTBY1NOMAXVALUE;--也可以直接使用简单默认参数:--CREATESEQUENCEseq_employee;SELECTseq_employee.NEXTV......
  • 题解:牛客周赛 Round 72(A-D)(E只有代码)
    先附上补题链接,没打的同学可以来补一下:https://ac.nowcoder.com/acm/contest/98256A小红的01串(一)题意找到一个01串中相邻字符不同的对数做法从头到尾扫一遍,计算前后不一样的字符就可以了#include<bits/stdc++.h>signedmain(){std::ios::sync_with_stdio(false)......
  • 题解:AT_abc266_c [ABC266C] Convex Quadrilateral
    思路对于一个凸多边形,它的任意内角一定小于\(45\degree\)。如果每相邻两条边的叉积的符号相同就说明它们是顺时针或逆时针排列的,则可以判别出该四边形是否为凸四边形。AC代码#include<bits/stdc++.h>usingnamespacestd;usingll=longlong;intX1,X2,X3,X4,Y1,Y2,Y3......