当前位置: 首页 > news >正文

Codeforces 2127 D(图论,组合数学,DFS,分类讨论)

Codeforces 2127 D

D. Root was Built by Love, Broken by Destiny

题意: n栋房子,其中有m做桥分别连接两栋房子,然后把这些房子分别排列在南北两岸顺序不限,排列的结果不能有任意两座桥相交,求排列的方案数

思路: 把这个问题抽象成图论问题首先,然后由不相交的边联想到森林,则必须m = (n - 1)才存在合法方案数,否则一定会相交,假设把度数为1的节点去掉后,如果剩余是一条链则是合法的(特别注意如果一个点度数大于2的子节点个数大于2则不会构成一条链),设链上的节点数为m则方案数为(\(\prod_{i=1}^m (cnt_i)!\))(cnt代表i节点度数为1的节点个数)。然后再考虑南北和链长度>=2时左右排列的两种状况。

Tag: 图论(抽象成树上问题,并最终抽象成一条链),组合数学(非链上节点的排列及左右朝向),DFS,分类讨论

点击查看代码
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using ull = unsigned long long;
#define endl "\n"
typedef pair<int, int> Pii;
#define REP(i, n) for (int i = 0; i < (n); ++i)
#define REP3(i, m, n) for (int i = (m); (i) < int(n); ++ (i))
#define rep(i,b) for(int i=(int)(0);i<(int)(b);i++)
#define rng(i,a,b) for(int i=int(a);i<int(b);i++)
#define ALL(x) begin(x), end(x)
#define rrep(i,a,b) for(int i=a;i>=b;i--)
#define fore(i,a) for(auto &i:a)
#define all(s) (s).begin(),(s).end()
#define drep2(i, m, n) for (int i = (m)-1; i >= (n); --i)
#define drep(i, n) drep2(i, n, 0)
#define rever(vec) reverse(vec.begin(), vec.end())
#define sor(vec) sort(vec.begin(), vec.end())
#define fi first
#define FOR_(n) for (ll _ = 0; (_) < (ll)(n); ++(_))
#define FOR(i, n) for (ll i = 0; (i) < (ll)(n); ++(i))
#define se second
#define pb push_back
#define P pair<ll,ll>
#define PQminll priority_queue<ll, vector<ll>, greater<ll>>
#define PQmaxll priority_queue<ll,vector<ll>,less<ll>>
#define PQminP priority_queue<P, vector<P>, greater<P>>
#define PQmaxP priority_queue<P,vector<P>,less<P>>
#define NP next_permutation
#define die(a) {cout<<a<<endl; return;}
#define dier(a) {return a;}
//const ll Mod = 1000000009;
//const ll Mod = 998244353;
const ll Mod = 1000000007;
#define inv(a) q_pow((ll)a, Mod - 2)
const ll inf = 4000000000000000000ll;
const ld eps = ld(0.00000000001);
static const long double pi = 3.141592653589793;
template<class T>void vcin(vector<T> &n){for(int i=0;i<int(n.size());i++) cin>>n[i];}
template<class T,class K>void vcin(vector<T> &n,vector<K> &m){for(int i=0;i<int(n.size());i++) cin>>n[i]>>m[i];}
template<class T>void vcout(vector<T> &n){for(int i=0;i<int(n.size());i++){cout<<n[i]<<" ";}cout<<endl;}
template<class T>void vcin(vector<vector<T>> &n){for(int i=0;i<int(n.size());i++){for(int j=0;j<int(n[i].size());j++){cin>>n[i][j];}}}
template<class T>void vcout(vector<vector<T>> &n){for(int i=0;i<int(n.size());i++){for(int j=0;j<int(n[i].size());j++){cout<<n[i][j]<<" ";}cout<<endl;}cout<<endl;}
void yes(bool a){cout<<(a?"yes":"no")<<endl;}
void YES(bool a){cout<<(a?"YES":"NO")<<endl;}
void Yes(bool a){cout<<(a?"Yes":"No")<<endl;}
void possible(bool a){ cout<<(a?"possible":"impossible")<<endl; }
void Possible(bool a){ cout<<(a?"Possible":"Impossible")<<endl; }
void POSSIBLE(bool a){ cout<<(a?"POSSIBLE":"IMPOSSIBLE")<<endl; }
#define FOR_R(i, n) for (ll i = (ll)(n)-1; (i) >= 0; --(i))
template<class T>auto min(const T& a){ return *min_element(all(a)); }
//template<class T>auto max(const T& a){ return *max_element(all(a)); }
template<class T,class F>void print(pair<T,F> a){cout<<a.fi<<" "<<a.se<<endl;}
template<class T>bool chmax(T &a,const T b) { if (a<b) { a=b; return 1; } return 0;}
template<class T>bool chmin(T &a,const T b) { if (b<a) { a=b; return 1; } return 0;}
template<class T> void ifmin(T t,T u){if(t>u){cout<<-1<<endl;}else{cout<<t<<endl;}}
template<class T> void ifmax(T t,T u){if(t>u){cout<<-1<<endl;}else{cout<<t<<endl;}}
ll fastgcd(ll u,ll v){ll shl=0;while(u&&v&&u!=v){bool eu=!(u&1);bool ev=!(v&1);if(eu&&ev){++shl;u>>=1;v>>=1;}else if(eu&&!ev){u>>=1;}else if(!eu&&ev){v>>=1;}else if(u>=v){u=(u-v)>>1;}else{ll tmp=u;u=(v-u)>>1;v=tmp;}}return !u?v<<shl:u<<shl;}
ll modPow(ll a, ll n, ll Mod) { if(Mod==1) return 0;ll ret = 1; ll p = a % Mod; while (n) { if (n & 1) ret = ret * p % Mod; p = p * p % Mod; n >>= 1; } return ret; }
vector<ll> divisor(ll x){ vector<ll> ans; for(ll i = 1; i * i <= x; i++){ if(x % i == 0) {ans.push_back(i); if(i*i!=x){ ans.push_back(x / ans[i]);}}}sor(ans); return ans; }
ll pop(ll x){return __builtin_popcountll(x);}
ll poplong(ll x){ll y=-1;while(x){x/=2;y++;}return y;}
P hyou(P a){ll x=fastgcd(abs(a.fi),abs(a.se));a.fi/=x;a.se/=x;if(a.se<0){a.fi*=-1;a.se*=-1;}return a;}
P Pplus(P a,P b){ return hyou({a.fi*b.se+b.fi*a.se,a.se*b.se});}
P Ptimes(P a,ll b){ return hyou({a.fi*b,a.se});}
P Ptimes(P a,P b){ return hyou({a.fi*b.fi,a.se*b.se});}
P Pminus(P a,P b){ return hyou({a.fi*b.se-b.fi*a.se,a.se*b.se});}
P Pgyaku(P a){ return hyou({a.se,a.fi});}ll q_pow(ll x, ll n) {ll res = 1;for (; n > 0; n /= 2) {if (n % 2) res = res * x % Mod;x = x * x % Mod;}return res % Mod;
}ll i, j;
ll n, m, k;
ll l, r, p, q;
ll a, b;
ll mul[200005];
void solve() {cin >> n >> m;vector<vector<int>> g(n);vector<int> cnt(n);for(int i = 0; i < m; ++i) {cin >> a >> b;--a;--b;g[a].pb(b);g[b].pb(a);cnt[a]++;cnt[b]++;}     if(m != (n - 1)) {cout << 0 << endl;return;}      ll count = 0;vector<bool> flag(n, false);for(int i = 0; i < n; ++i) {int nxt = 0;if(cnt[i] == 1) continue;for(auto j : g[i]) {if(cnt[j] >= 2) {if(nxt >= 2) {  // 如果度数为2的点过多,则不能成链,方案数为0cout << 0 << endl;return;}else {nxt++;}   // 记录度数大于等于2的节点数}}flag[i] = true;    // 处于链子上count++;}ll res = 2LL;   // 南北     for(int i = 0; i < n; ++i) {if(!flag[i]) continue;ll c = 0;for(auto j : g[i]) {    // 记录链上度数节点为1的数量if(cnt[j] == 1 && !flag[j]) {c++;} }res = (res * mul[c]) % Mod; // 累乘链上度数为1的节点数量的阶乘,等价于这些节点的任意排列}if(count >= 2) res = (res * 2LL) % Mod;  // 如果链子的长度大于2,则需要考虑链子左右的排列cout << res << endl;
}
int main() {std::ios::sync_with_stdio(false);std::cin.tie(0);std::cout.tie(0);mul[0] = 1;for(ll i = 1; i < 200005; ++i) {mul[i] = mul[i - 1] * i;mul[i] %= Mod;}int t;cin >> t;while(t--) solve();
}
http://www.hskmm.com/?act=detail&tid=13649

相关文章:

  • Java学习笔记:从三个实验看编程思维的锤炼
  • 题解:AT_arc068_d [ARC068F] Solitaire
  • Codeforces Round 1051 (Div. 2) D1D2题解
  • JSP
  • 每日博客
  • 探展打卡 Serverless,2025 云栖大会来了
  • 从 0 到 1,AI 走进服装店:记住每位顾客的喜好,比你还靠谱
  • STM32HAL 飞快入门(十九):UART 编程(二)—— 中断方式实现收发及局限分析
  • 贪心算法应用:多重背包启发式疑问详解
  • 划重点|云栖大会「AI 原生应用架构论坛」看点梳理
  • 君子如水,心中有火:vivo本心而为30周年
  • Margin 塌陷问题如何解决?触发BFC。BFC的概念和触发条件
  • 9.22
  • 数字统计
  • 火速收藏!2025 云栖大会 AI 中间件议程看点全公开(附免费报名通道)
  • 第二次软工作业——个人项目 - LXJ
  • WinForm引入项目资源文件
  • 第二次作业
  • 训练集,验证集,测试集
  • Android 项目:画图白板APP开发(六)——分页展示 - 教程
  • ESP32 读取旋转编码器
  • mysql/oracle LEFT JOIN 取时间最大的数据
  • 6月6日证书 - 工信部人才交流中心PostgreSQL中级PGCP高级PGCM认证
  • 基于遗传算法与非线性规划的混合优化算法在电力系统最优潮流中的实现
  • 【下一款产品】
  • 数1的个数
  • 通过ML.Net调用Yolov5的Onnx模型
  • Java-如何在Eclipse开发-数组
  • 常用数据生成器
  • 基于RSSI修正的定位算法分析