题目:告诉你每两个点之间的最短路距离。构造每条边边权<=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).