UOJ

思路

我们知道关于有向图欧拉回路计数有一个结论:在每个点入度等于出度的时候,答案就是

\[t_w(G)\prod (deg_i-1)!
\]

其中\(t_w(G)\)是以某个点为根的树形图个数。(必须确定是外向树还是内向树)

(由这个公式,我们可以知道这种图下面以每个点为根的外向树和内向树的个数都是一样的,但我不会证/kk)

还有一个结论,不过这题用不上:对于一个有向图,以点\(x\)为根的树的个数是用度数矩阵减去邻接矩阵,再删去第\(x\)行第\(x\)列,的行列式。其中那个度数矩阵如果求内向树那么就是出度,外向树就是入度。

所以在图是一棵树的时候,显然每组边都会有一半向上一半向下,就可以得到答案。

基环树的时候,其实问题就转化为给环上的边定向。

我们可以枚举某一条边的定向方案,然后就可以推出其他所有边。

然后再求一下树形图个数,就做完了。

代码

#include<bits/stdc++.h>
clock_t t=clock();
namespace my_std{
using namespace std;
#define pii pair<int,int>
#define fir first
#define sec second
#define MP make_pair
#define rep(i,x,y) for (int i=(x);i<=(y);i++)
#define drep(i,x,y) for (int i=(x);i>=(y);i--)
#define go(x) for (int i=head[x];i;i=edge[i].nxt)
#define templ template<typename T>
#define sz 10101
#define mod 998244353ll
typedef long long ll;
typedef double db;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
templ inline T rnd(T l,T r) {return uniform_int_distribution<T>(l,r)(rng);}
templ inline bool chkmax(T &x,T y){return x<y?x=y,1:0;}
templ inline bool chkmin(T &x,T y){return x>y?x=y,1:0;}
templ inline void read(T& t)
{
t=0;char f=0,ch=getchar();double d=0.1;
while(ch>'9'||ch<'0') f|=(ch=='-'),ch=getchar();
while(ch<='9'&&ch>='0') t=t*10+ch-48,ch=getchar();
if(ch=='.'){ch=getchar();while(ch<='9'&&ch>='0') t+=d*(ch^48),d*=0.1,ch=getchar();}
t=(f?-t:t);
}
template<typename T,typename... Args>inline void read(T& t,Args&... args){read(t); read(args...);}
char __sr[1<<21],__z[20];int __C=-1,__zz=0;
inline void Ot(){fwrite(__sr,1,__C+1,stdout),__C=-1;}
inline void print(register int x)
{
if(__C>1<<20)Ot();if(x<0)__sr[++__C]='-',x=-x;
while(__z[++__zz]=x%10+48,x/=10);
while(__sr[++__C]=__z[__zz],--__zz);__sr[++__C]='\n';
}
void file()
{
#ifdef NTFOrz
freopen("a.in","r",stdin);
#endif
}
inline void chktime()
{
#ifndef ONLINE_JUDGE
cout<<(clock()-t)/1000.0<<'\n';
#endif
}
#ifdef mod
ll ksm(ll x,int y){ll ret=1;for (;y;y>>=1,x=x*x%mod) if (y&1) ret=ret*x%mod;return ret;}
ll inv(ll x){return ksm(x,mod-2);}
#else
ll ksm(ll x,int y){ll ret=1;for (;y;y>>=1,x=x*x) if (y&1) ret=ret*x;return ret;}
#endif
// inline ll mul(ll a,ll b){ll d=(ll)(a*(double)b/mod+0.5);ll ret=a*b-d*mod;if (ret<0) ret+=mod;return ret;}
}
using namespace my_std; ll fac[sz<<10],_fac[sz<<10];
void init()
{
_fac[0]=fac[0]=1;
rep(i,1,sz*1e3) fac[i]=fac[i-1]*i%mod;
_fac[sz*(int)1e3]=inv(fac[sz*(int)1e3]);
drep(i,sz*1e3-1,1) _fac[i]=_fac[i+1]*(i+1)%mod;
}
ll C(int n,int m){return n>=m&&m>=0?fac[n]*_fac[m]%mod*_fac[n-m]%mod:0;} int n,m;
struct hh{int t,nxt,cnt;}edge[sz<<1];
int head[sz],ecnt=1;
int deg[sz];
void make_edge(int f,int t,int cc)
{
edge[++ecnt]=(hh){t,head[f],cc};
head[f]=ecnt;
edge[++ecnt]=(hh){f,head[t],cc};
head[t]=ecnt;
deg[f]+=cc,deg[t]+=cc;
} namespace Tree
{
int solve()
{
ll ans=1;
rep(i,1,n) ans=ans*fac[deg[i]/2-1]%mod;
rep(i,1,n-1) ans=ans*C(edge[i<<1].cnt,edge[i<<1].cnt/2)%mod*edge[i<<1].cnt/2%mod;
cout<<ans;
return 0;
}
} namespace WTF
{
ll prod=1;
int incir[sz];
vector<pii>cir; // fir: the point in the circle; sec: the edge that connects itself and the previous one
int vis[sz],in[sz];
#define v edge[i].t
int dfs(int x,int fa)
{
int ret=0,id=0;
in[x]=vis[x]=1;
go(x) if (v!=fa)
{
if (!vis[v])
{
int cur=dfs(v,x);
if (!cur) { prod=prod*C(edge[i].cnt,edge[i].cnt/2)%mod*edge[i].cnt/2%mod; continue; }
ret=cur;id=i;
}
else if (in[v]) ret=v,id=i;
}
if (ret) cir.push_back(MP(x,id)),incir[x]=1;
if (ret==x) ret=0;
prod=prod*fac[deg[x]/2-1]%mod;
in[x]=0;
return ret;
}
#undef v
int L[sz],R[sz]; // 出度
int L_[sz],R_[sz]; // 入度
ll pre[sz],suf[sz];
int solve()
{
dfs(1,0);
int m=(int)cir.size()-1;
ll ans=0;
rep(k,0,edge[cir[0].sec].cnt)
{
R_[m]=L[0]=k;R[m]=L_[0]=edge[cir[0].sec].cnt-k;
rep(i,0,m-1)
{
int delta=L[i]-L_[i],cnt=edge[cir[i+1].sec].cnt;
L_[i+1]=R[i]=(cnt-delta)/2;L[i+1]=R_[i]=(cnt+delta)/2;
}
bool flg=1;
rep(i,0,m) if (L[i]<0||R[i]<0) flg=0;
if (!flg) continue;
ll cur=prod;
rep(i,0,m) cur=cur*C(edge[cir[i].sec].cnt,L[i])%mod;
pre[0]=1;rep(i,1,m) pre[i]=pre[i-1]*L[i]%mod;
suf[m+1]=1;drep(i,m,1) suf[i]=suf[i+1]*R[i]%mod;
rep(i,0,m) (ans+=cur*pre[i]%mod*suf[i+1]%mod)%=mod;
}
cout<<ans;
return 0;
}
} int main()
{
file();
init();
read(n,m);
int x,y,z;
rep(i,1,m) read(x,y,z),make_edge(x,y,z);
rep(i,1,n) if (deg[i]&1) return puts("0"),0;
if (m==n-1) return Tree::solve();
return WTF::solve();
}

UOJ226. 【UR #15】奥林匹克环城马拉松 [组合数学,图论]的更多相关文章

  1. 【uoj#225】[UR #15]奥林匹克五子棋 构造

    题目描述 两个人在 $n\times m$ 的棋盘上下 $k$ 子棋,问:是否存在一种平局的情况?如果存在则输出一种可能的最终情况. 输入 第一行三个正整数 $n,m,k$ ,意义如前所述. 输出 如 ...

  2. UOJ Round #15 [构造 | 计数 | 异或哈希 kmp]

    UOJ Round #15 大部分题目没有AC,我只是水一下部分分的题解... 225[UR #15]奥林匹克五子棋 题意:在n*m的棋盘上构造k子棋的平局 题解: 玩一下发现k=1, k=2无解,然 ...

  3. WinAFL

    winafl 标签(空格分隔): fuzz 构成 afl-fuzz.c 主模块 读取文件 维护testcase queue 进行mutate fuzz_one 评估代码覆盖率 执行遗传算法 更新界面 ...

  4. 转:智能模糊测试工具 Winafl 的使用与分析

    本文为 椒图科技 授权嘶吼发布,如若转载,请注明来源于嘶吼: http://www.4hou.com/technology/2800.html 注意: 函数的偏移地址计算方式是以IDA中出现的Imag ...

  5. 关于SPFA算法的优化方式

    关于SPFA算法的优化方式 这篇随笔讲解信息学奥林匹克竞赛中图论部分的求最短路算法SPFA的两种优化方式.学习这两种优化算法需要有SPFA朴素算法的学习经验.在本随笔中SPFA朴素算法的相关知识将不予 ...

  6. HDU-6125-Friend-Graph-2017CCPC网络赛(图论,拉姆齐定理-组合数学)

    Friend-Graph Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) To ...

  7. Python小白的数学建模课-15.图论基本概念

    图论中所说的图,不是图形图像或地图,而是指由顶点和边所构成的图形结构. 图论不仅与拓扑学.计算机数据结构和算法密切相关,而且正在成为机器学习的关键技术. 本系列结合数学建模的应用需求,来介绍 Netw ...

  8. 【uoj#22】[UR #1]外星人 组合数学+dp

    题目描述 给你一个长度为 $n$ 的序列 $\{a_i\}$ 和一个数 $x$ ,对于任意一个 $1\sim n$ 的排列 $\{p_i\}$ ,从 $1$ 到 $n$ 依次执行 $x=x\ \tex ...

  9. 刷题向》图论》BZOJ1179 关于tarjan和SPFA的15秒(normal)

    这道题可以考察图论的掌握程度(算半道水题) 题目如下 输入 第一行包含两个整数N.M.N表示路口的个数,M表示道路条数.接下来M行,每行两个整数,这两个整数都在1到N之间,第i+1行的两个整数表示第i ...

随机推荐

  1. 【洛谷 P4052】 [JSOI2007]文本生成器(AC自动机,DP)

    题目链接 AC自动机上dp第一题嗷. 如果直接求可读文本的数量,显然要容斥,不好搞. 于是考虑求不可读文本的数量,再用\(26^m\)减去其即可. 建出AC自动机,如果一个节点为单词结尾或其fail链 ...

  2. Postgres 多实例实例部署方式

    Postgres 数据库在原有示例正常运行情况下,新增一个端口示例,主要目的解决新的项目和原有项目的数据库部署不在冲突,可以独立运行,备份和还原数据互不影响,主要用的的命令有  initdb 数据库初 ...

  3. gitlab异地备份并验证MD5值

    最近公司发生了蛮多事情的,唉,咱也不管问啊,好好干活吧 需求 把gitlab的备份文件异地备份一份,备份无论失败还是成功通知某邮箱 实现思路 先rsync文件过去,判断rsync这个步骤有没有成功,失 ...

  4. Keil MDK fromelf生成bin文件

    找到Keil安装目录中fromelf.exe 配置Keil fromelf.exe --bin -o -\OBJ\LED.bin -\OBJ\LED.axf –bin:二进制文件 –i32:Intel ...

  5. The server quit without updating PID file

    [root@fjgh ~]# service mysqld start Starting MySQL... ERROR! The server quit without updating PID fi ...

  6. Python学习日记(五) 编码基础

    初始编码 ASCII最开始为7位,一共128字符.最后确定8位,一共256个字符,最左边的为拓展位,为以后的开发做准备. ASCII码的最左边的一位为0. 基本换算:8位(bit) = 1字节(byt ...

  7. MySQL Connection--使用tcpkill杀掉MySQL活跃连接

    当MySQL连接被打满,连管理员也无法本地登录时,可以考虑使用tcpkill杀掉一些应用服务器创建的连接. CentOS 6安装tcpkill rpm安装包: libnids-1.24-1.el6.x ...

  8. 【JUC】7.CountDownLatch

    Latch:门闩.一种线程通信的方式:当程序不涉及同步,仅仅需要线程通信的时候,使用synchronize或者lock的线程通信等待唤醒机制,就显得太重了: 这时候,可以考虑使用信号量类:CountD ...

  9. python之变量的数据类型(1)int 、bool 、str 及for循环运用

    一.变量的数据类型(1) 1.int 类型 int类型是整数,常用的有bit_length() 方法 用来返回一个数的二进制长度 2.bool类型 布尔型只有两个值 True,False 有关类型转换 ...

  10. systemd_journal_no_entries问题解决

    问题: #journalctl Journal file /var/log/journal/410/system@0.journal~ uses an unsupported feature, ign ...