一本通 黑暗城堡
阿新 • • 發佈:2020-12-06
描述
你知道黑暗城堡有 NN個房間,MM 條可以製造的雙向通道,以及每條通道的長度。
城堡是樹形的並且滿足下面的條件:
設 DiDi為如果所有的通道都被修建,第 ii 號房間與第 11 號房間的最短路徑長度;
而SiSi 為實際修建的樹形城堡中第 ii 號房間與第 11 號房間的路徑長度;
要求對於所有整數 ii (1≤i≤N1≤i≤N),有 Si=DiSi=Di 成立。
你想知道有多少種不同的城堡修建方案。當然,你只需要輸出答案對 231−1231−1 取模之後的結果就行了。
輸入
第一行為兩個由空格隔開的整數 N,MN,M;
第二行到第 M+1M+1 行為 33個由空格隔開的整數x,y,lx,y,l:表示 xx 號房間與 yy 號房間之間的通道長度為ll。
輸出
一個整數:不同的城堡修建方案數對 231−1231−1 取模之後的結果。
樣例輸入
4 6
1 2 1
1 3 2
1 4 3
2 3 1
2 4 2
3 4 1
樣例輸出
6
思路:普普通通的dijk可能有重邊所以記得取最小的。對所有的邊求完最短路後,可能會存在某兩個點之間存在好幾個長度一樣的最短路;
最後看一下兩個點之間可以有幾條一樣最短路,計數就可。
if (dis[i]==dis[j]+e[j][i])
#include <string.h> #include <stdio.h> #include <math.h> #include <algorithm> using namespace std; typedef long long ll; const int maxn=1e4+10,inf=0x3f3f3f; ll mod=pow(2,31)-1; int dis[maxn],book[maxn],e[maxn][maxn],n,m; void dijk() { int minn,k,i,j,u; memset(dis,0,sizeof(dis)); memset(book,0,sizeof(book)); for (i=1; i<=n; i++) dis[i]=e[1][i];// book[1]=1; for (i=1; i<n; i++) { minn=inf; for (j=1; j<=n; j++) { if (!book[j]&&dis[j]<minn) { minn=dis[j]; u=j; } } book[u]=1; for (j=1; j<=n; j++) { if (!book[j]) dis[j]=min(dis[u]+e[u][j],dis[j]); } } } int main() { int i,j; scanf("%d%d",&n,&m); for (i=1; i<=n; i++) for (j=1; j<=n; j++) if (i==j) e[i][j]=0; else e[i][j]=inf; while(m--) { int x,y,l; scanf("%d %d %d",&x,&y,&l); e[x][y]=e[y][x]=min(e[x][y],l); } dijk(); ll ans=1; int cnt; for (i=2; i<=n; i++) { cnt=0; for (j=1; j<=n; j++) { if (e[i][j]) { if (dis[i]==dis[j]+e[j][i]) cnt++;// } } ans=(ans*cnt)%mod; } printf("%lld\n",ans); return 0; }