zoukankan      html  css  js  c++  java
  • uoj279 题目交流通道

    题目:告诉你每两个点之间的最短路距离。构造每条边边权<=m的无向完全图。求有多少种不同边权的图满足最短路限制?n<=400.

    标程:

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 using namespace std;
     5 typedef long long ll;
     6 const int mod=998244353;
     7 const int N=405;
     8 int n,a[N][N],c[N][N],g[N],f[N],sz[N],h[N],ans,m;
     9 bool ok()
    10 {
    11     for (int i=1;i<=n;i++) if (a[i][i]) return 0;
    12     for (int i=1;i<=n;i++)
    13       for (int j=i+1;j<=n;j++) if (a[i][j]!=a[j][i]||a[i][j]>m) return 0;
    14     for (int i=1;i<=n;i++)
    15       for (int j=i+1;j<=n;j++)
    16         for (int k=1;k<=n;k++)
    17           if ((ll)a[i][k]+a[k][j]<a[i][j]) return 0;
    18     return 1;
    19 }
    20 int find(int x) {return x==f[x]?x:f[x]=find(f[x]);}
    21 int ksm(int x,int y)
    22 {
    23     int res=1;
    24     while (y) {if (y&1) res=(ll)res*x%mod; x=(ll)x*x%mod; y>>=1;}
    25     return res;
    26 }
    27 void init()
    28 {
    29     for (int i=0;i<=n;i++) c[i][0]=1;
    30     for (int i=1;i<=n;i++)
    31       for (int j=1;j<=i;j++) c[i][j]=((ll)c[i-1][j]+c[i-1][j-1])%mod;
    32 }
    33 int main()
    34 {
    35     scanf("%d%d",&n,&m);init(); ans=1;
    36     for (int i=1;i<=n;i++)  
    37       for (int j=1;j<=n;j++) scanf("%d",&a[i][j]);
    38     if (!ok()) return puts("0"),0;
    39     for (int i=1;i<=n;i++) f[i]=i;
    40     for (int i=1;i<=n;i++) 
    41       for (int j=i+1;j<=n;j++) if (!a[i][j]) f[find(i)]=find(j);
    42     for (int i=1;i<=n;i++) sz[find(i)]++;
    43     for (int i=1;i<=n;i++) 
    44      if (f[i]==i)
    45       for (int j=i+1,k;j<=n;j++)
    46         if (f[j]==j)
    47         {
    48             for (k=1;k<=n;k++)
    49             if (f[k]==k&&k!=i&&k!=j&&a[i][j]==(ll)a[i][k]+a[k][j]) break;
    50           int ts=sz[i]*sz[j];
    51            if (k<=n) ans=(ll)ans*ksm(m-a[i][j]+1,ts)%mod;
    52             else ans=(ll)ans*(ksm(m-a[i][j]+1,ts)-ksm(m-a[i][j],ts)+mod)%mod;
    53          }    
    54    for (int i=1;i<=n;i++) 
    55    {
    56       g[i]=h[i]=ksm(m+1,i*(i-1)/2);//h[i]表示i个点不保证mst=0的方案数。g[i]表示包含1点和其他i-1个点中保证有mst=0的方案数。
    57       for (int j=1;j<i;j++)
    58         g[i]=(ll)(g[i]-(ll)g[j]*h[i-j]%mod*c[i-1][j-1]%mod*ksm(m,j*(i-j))%mod+mod)%mod;
    59     }
    60     for (int i=1;i<=n;i++) if (f[i]==i) ans=(ll)ans*g[sz[i]]%mod;
    61     printf("%d
    ",ans);
    62    return 0;
    63 }

    易错点:1.不要漏取模。

    题目:性质+并查集+容斥dp

    特判一下不合法(无解)的情况。

    考虑一张没有0边的图(如果有0边的话ijk三角形中会有两条边被判作无用),当a[i,j]=a[i,k]+a[k,j]时,a[i,j]这条边可以在a[i,j]~m中任取,这条边是没有贡献的。

    考虑特殊的0边,如果有一些点对的距离为0,那么就用并查集缩起来,那么这个图就变成了若干个连通块,每个连通块中的点对之间的距离都是0。

    所以就可以在连通块之间做没有0边的情况(两个连通块之间的所有边应该都是相等的,一条边的贡献可以直接统计sz[i]*sz[j]次),在连通块内用套路容斥出mst=0的边权方案数。

    复杂度O(n^3).

  • 相关阅读:
    POJ 1966 Cable TV Network
    POJ 3204 Ikki's Story I
    Codeforces Round #388 (Div. 2)
    BZOJ 后缀自动机四·重复旋律7
    扩展欧几里得 exGCD
    网络流模板 NetworkFlow
    BZOJ 2002: [Hnoi2010]Bounce 弹飞绵羊
    BZOJ 3224: Tyvj 1728 普通平衡树
    BZOJ 1070: [SCOI2007]修车
    BZOJ 4552: [Tjoi2016&Heoi2016]排序
  • 原文地址:https://www.cnblogs.com/Scx117/p/8708281.html
Copyright © 2011-2022 走看看