模板-最小生成树计数

来源:互联网 发布:淘宝上取消了分流 编辑:程序博客网 时间:2024/06/05 11:25
//最小生成树计数#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-nstruct 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 >> mod, n + m + mod) {        init();        while (m--) {            rd(u);            rd(v);            rd(d);            add(u, v, d);        }        pt(cal_MST_count(n, mod));        putchar('\n');    }    return 0;}

0 0
原创粉丝点击