黑暗城堡
(castle.pas/c/cpp)
題目描述
在順利攻破 Lord lsp 的防線之后,lqr 一行人來到了 Lord lsp 的城堡下方。Lord lsp 黑化之后雖然擁有了強大的超能力,能夠用意念力制造建築物,但是智商水平卻沒怎么增加。現在 lqr 已經搞清楚黑暗城堡有 N 個房間,M 條可以制造的雙向通道,以及每條通道的長度。
lqr 深知 Lord lsp 的想法, 為了避免每次都要琢磨兩個房間之間的最短路徑,Lord lsp一定會把城堡修建成樹形的; 但是,為了盡量提高自己的移動效率,Lord lsp 一定會使得城堡滿足下面的條件:設 Di 為如果所有的通道都被修建, 第 i 號房間與第 1 號房間的最短路徑長度;而 Si 為實際修建的樹形城堡中第 i 號房間與第
1 號房間的路徑長度,對於所有滿足 1≤i≤N 的整數 i,有 Si = Di。為了打敗 Lord lsp,lqr 想知道有多少種不同的城堡修建方案。於是 lqr 向 applepi 提出了這個問題。由於 applepi 還要忙着出模擬賽,所以這個任務就交給你了。當然,你只需要輸出答案對 231 – 1 取模之后的結果就行了。
輸入格式
第一行有兩個整數 N 和 M。
之后 M 行,每行三個整數 X,Y 和 L,表示可以修建 X 和 Y 之間的一條長度為 L 的通道。
輸出格式
輸出一個整數,表示答案對 231 – 1 取模之后的結果。
樣例輸入
3 |
3 |
|
1 |
2 |
2 |
1 |
3 |
1 |
2 |
3 |
1 |
樣例輸出
2
數據范圍與約定
對於 30% 的數據,2≤N≤5,M≤10。
對於 50% 的數據,滿足條件的方案數不超過 10000。
對於 100% 的數據,2≤N≤1000,N – 1≤M≤N(N – 1)/2,1≤L≤100。
題目要求源點到其余點的最短路徑d[i],並且求樹上路徑s[i]等於d[i]的生成樹
所以先求出最短路徑d[i],並記錄d[i[是哪個點的最短路徑屬性為v;
然后按長度大小進行排序,為了避免重復計數,,最后把滿足d[x]=d[y]+w[i][j]的一個點一個點的往生成樹之中加
根據乘法原理求出答案即可
#include<cstdio> #include<algorithm> #include<cstring> #include<queue> using namespace std; typedef long long ll; const int maxn=1010; const ll nil=(long long)1<<40-1; #define mod ((1<<31)-1) struct my{ int v,next; ll w; }; struct lmjer{ int v; ll w; }; struct node{ int u; ll w; bool operator<(const node &rhs)const{ return w>rhs.w; } }; int fa,adj[maxn],n,m; ll tu[maxn][maxn]; lmjer d[maxn]; bool done[maxn]; priority_queue<node>Q; my bian[maxn*maxn]; void myinsert(int u,int v,ll w){ bian[++fa].v=v; bian[fa].next=adj[u]; bian[fa].w=w; adj[u]=fa; } void dijkstra(int s){ for (int i=1;i<=n;i++) d[i].w=nil,d[i].v=i; d[s].w=0; node x; x.u=s; x.w=0; Q.push(x); while(!Q.empty()){ x=Q.top();Q.pop(); int u=x.u; if(done[u]) continue; done[u]=true; for (int i=adj[u];i;i=bian[i].next){ int v=bian[i].v; if(d[v].w>d[u].w+bian[i].w){ d[v].w=d[u].w+bian[i].w; x.u=v; x.w=d[v].w; Q.push(x); } } } } bool cmp(const lmjer a,const lmjer b){ return a.w<b.w; } int main(){ scanf("%d%d",&n,&m); memset(tu,10,sizeof(tu)); int u,v; ll w; for (int i=1;i<=m;i++){ scanf("%d%d%lld",&u,&v,&w); myinsert(u,v,w); myinsert(v,u,w); tu[u][v]=tu[v][u]=min(tu[u][v],w); } dijkstra(1); sort(d+1,d+1+n,cmp); int ans=1; for (int i=2;i<=n;i++){ ll temp=0; for (int j=1;j<i;j++){ int x=d[i].v,y=d[j].v; if(d[i].w==d[j].w+tu[x][y]) temp++; } ans=(long long)ans*temp%mod; } printf("%d\n",ans); return 0; }