BZOJ1016 && JSOI2008] 最小生成树计数
题目链接: id=1016">点击打开链接
裸题
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
template <class T>
inline bool rd(T &ret) {
char c; int sgn;
if (c = getchar(), c == EOF) return 0;
while (c != '-' && (c<'0' || c>'9')) c = getchar();
sgn = (c == '-') ? -1 : 1;
ret = (c == '-') ? 0 : (c - '0');
while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0');
ret *= sgn;
return 1;
}
template <class T>
inline void pt(T x) {
if (x <0) {
putchar('-');
x = -x;
}
if (x>9) pt(x / 10);
putchar(x % 10 + '0');
}
using namespace std;
typedef long long ll;
const int N = 105; //点的个数
const int M = 1005; //边的个数
//点标从1-n
struct node {
int set[N];
void init(int n) {
for (int i = 0; i <= n; i++) set[i] = i;
}
int find(int x) {
return x == set[x] ? x : set[x] = find(set[x]);
}
int Union(int x, int y) {
int xx = find(x);
int yy = find(y);
if (xx == yy) return -1;
set[xx] = yy;
return 1;
}
}a, b, c; struct Node {
int u, v, dis;
}edge[M];
int edgenum;
void add(int u, int v, int d){
Node E = { u, v, d };
edge[++edgenum] = E;
} bool visit[N];
vector<int> g[N];
ll p[N][N], deg[N][N];
int cmp(Node a, Node b) {
return a.dis < b.dis;
}
ll DET(ll a[][N], int n, ll MOD)
{
int i, j, k;
ll temp = 1, t;
for (i = 0; i < n; i++) for (j = 0; j < n; j++) a[i][j] %= MOD;
for (i = 1; i < n; i++)
{
for (j = i + 1; j < n; j++) while (a[j][i])
{
t = a[i][i] / a[j][i];
for (k = i; k < n; k++)
{
a[i][k] -= a[j][k] * t;
a[i][k] %= MOD;
}
for (k = i; k < n; k++)
swap(a[i][k], a[j][k]); temp = -temp;
}
temp = temp*a[i][i] % MOD;
}
return (temp + MOD) % MOD;
} ll cal_MST_count(int n, ll MOD) {
sort(edge + 1, edge + edgenum + 1, cmp);
int pre = edge[1].dis;
ll ans = 1;
a.init(n);
b.init(n);
memset(visit, 0, sizeof(visit));
memset(deg, 0, sizeof(deg));
for (int i = 0; i <= n; i++) g[i].clear();
for (int t = 1; t <= edgenum + 1; t++)
{
if (edge[t].dis != pre || t == edgenum + 1)
{
for (int i = 1, k; i <= n; i++) if (visit[i])
{
k = b.find(i);
g[k].push_back(i);
visit[i] = 0;
}
for (int i = 1; i <= n; i++)
if (g[i].size())
{
memset(p, 0, sizeof(p));
for (int j = 0; j < g[i].size(); j++)
for (int k = j + 1, x, y; k < g[i].size(); k++)
{
x = g[i][j];
y = g[i][k];
p[j][k] = p[k][j] = -deg[x][y];
p[j][j] += deg[x][y];
p[k][k] += deg[x][y];
}
ans = ans*DET(p, g[i].size(), MOD) % MOD;
for (int j = 0; j < g[i].size(); j++) a.set[g[i][j]] = i;
}
memset(deg, 0, sizeof(deg));
for (int i = 1; i <= n; i++)
{
b.set[i] = a.find(i);
g[i].clear();
}
if (t == edgenum + 1) break;
pre = edge[t].dis;
}
int x = a.find(edge[t].u);
int y = a.find(edge[t].v);
if (x == y) continue;
visit[x] = visit[y] = 1;
b.Union(x, y);
deg[x][y]++;
deg[y][x]++;
}
if (!edgenum) return 0;
for (int i = 2; i <= n; i++)
if (b.find(i) != b.find(1))
return 0;
return ans;
}
void init(){ edgenum = 0; }
int n, m, u, v, d;
ll mod;
int main(){
while (cin >> n >> m){
init();
while (m--){
rd(u); rd(v); rd(d);
add(u, v, d);
}
pt(cal_MST_count(n, 31011LL)); putchar('\n');
}
return 0;
}
BZOJ1016 && JSOI2008] 最小生成树计数的更多相关文章
- bzoj1016 [JSOI2008]最小生成树计数
1016: [JSOI2008]最小生成树计数 Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 3517 Solved: 1396[Submit][St ...
- bzoj1016: [JSOI2008]最小生成树计数(kruskal+dfs)
1016: [JSOI2008]最小生成树计数 题目:传送门 题解: 神题神题%%% 据说最小生成树有两个神奇的定理: 1.权值相等的边在不同方案数中边数相等 就是说如果一种方案中权值为1的边有n条 ...
- BZOJ1016:[JSOI2008]最小生成树计数(最小生成树,DFS)
Description 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树.(如果两颗最小生成树中至少有一条边不同,则这两个最小生成树就是不同的 ...
- [bzoj1016][JSOI2008]最小生成树计数 (Kruskal + Matrix Tree 定理)
Description 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树.(如果两颗最小生成树中至少有一条边不同,则这两个最小生成树就是不同的 ...
- 【Matrix-tree定理】【并查集】【kruscal算法】bzoj1016 [JSOI2008]最小生成树计数
题意:求一个图的最小生成树个数. 矩阵树定理:一张无向图的生成树个数 = (度数矩阵 - 邻接矩阵)的任意一个n-1主子式的值. 度数矩阵除了对角线上D[i][i]为i的度数(不计自环)外,其他位置是 ...
- [BZOJ1016][JSOI2008]最小生成树计数(结论题)
题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1016 分析: 首先有个性质:如果边集E.E'都可以表示一个图G的最小生成树(当然E和E ...
- [BZOJ1016] [JSOI2008] 最小生成树计数 (Kruskal)
Description 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树.(如果两颗最小生成树中至少有一条边不同,则这两个最小生成树就是不同的 ...
- 【最小生成树】BZOJ1016: [JSOI2008]最小生成树计数
Description 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树.(如果两颗最小生成树中至少有一条边不同,则这两个最小生成树就是不同的 ...
- 2018.09.24 bzoj1016: [JSOI2008]最小生成树计数(并查集+搜索)
传送门 正解是并查集+矩阵树定理. 但由于数据范围小搜索也可以过. 我们需要知道最小生成树的两个性质: 不同的最小生成树中,每种权值的边出现的个数是确定的 不同的生成树中,某一种权值的边连接完成后,形 ...
- [BZOJ1016][JSOI2008]最小生成树计数 最小生成树 搜索
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1016 做这道题之前需要知道一些结论,同一个图的最小生成树中相同权值的边的个数是不会变的,如 ...
随机推荐
- 第二天,学习if,变量,注释
zz_age = 31guss_age=int(input("input your answer:"))if guss_age == zz_age: print ("Yo ...
- 有上下界的网络流 loj115 loj116 loj 117
参考文章 无源汇有上下界的可行流 有源汇有上下界的最大流 有源汇有上下界的最小流 无源汇有上下界可行流 以 loj115 为例. 剥离出必要边与自由边. #include <iostream&g ...
- 大数据学习——hadoop2.x集群搭建
1.准备Linux环境 1.0先将虚拟机的网络模式选为NAT 1.1修改主机名 vi /etc/sysconfig/network NETWORKING=yes HOSTNAME=itcast ### ...
- UVALive 2957 Bring Them There
Bring Them There Time Limit: 3000ms Memory Limit: 131072KB This problem will be judged on UVALive. O ...
- xtu summer individual 1 A - An interesting mobile game
An interesting mobile game Time Limit: 1000ms Memory Limit: 32768KB This problem will be judged on H ...
- zoj 2807 Electrical Outlets
Electrical Outlets Time Limit: 2 Seconds Memory Limit: 65536 KB Roy has just moved into a new a ...
- 【CSS】position relative 用法
Relative是position的一个属性,是相对定位. position的默认值是static,(也就是说对于任意一个元素,如果没有定义它的position属性,那么它的position:stat ...
- HDU-1041-Computer Transformation,大数递推,水过~~
Computer Transformatio ...
- [Kubernetes]Volume
容器技术使用rootfs机制和Mount Namespace,构建出一个同宿主机完全隔离开的文件系统环境 那容器里进程新建的文件,怎么样才能让宿主机获取到?宿主机上的文件和目录,怎么样才能让容器里的进 ...
- hdu 3371
#include<stdio.h> #include<stdlib.h> #define N 501 struct node { int x,y,dis; }road[N*N] ...