一本通 3.1 例 1」黑暗城堡
阿新 • • 發佈:2018-09-05
names lld edge 數據 需要 tor getchar() 你知道 結果
描述
你知道黑暗城堡有 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
咳咳,我覺得這道題定三級實在有點過分(因為我現在也很糊)
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<queue> #define inf 0x3f3f3f3f3f3f #define ll long long #define modd 2147483647 using namespace std; ll read(){ ll x=0,f=1;char ch; while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+(ch-'0');ch=getchar();} return x*f; } struct node{ ll u,v,w,nxt; }e[2000101]; struct node2{ ll w,id; }dis[100101]; ll fir[1000101],cnt=0; ll n,m,s,ed; ll vis[1000101]; ll pos[1001][1001]; struct edge{ ll u,dis; bool operator < (const edge& lala)const{ return dis>lala.dis; } }; void add(ll x,ll y,ll z){ e[++cnt].nxt=fir[x];e[cnt].u=x;e[cnt].v=y;e[cnt].w=z;fir[x]=cnt; } void dijis(ll st){ priority_queue<edge> q; for(ll i=1;i<=n;i++)dis[i].w=inf,dis[i].id=i; dis[st].w=0;dis[st].id=1;q.push((edge){st,0}); while(!q.empty()){ edge x=q.top();q.pop(); ll u=x.u,d=x.dis; if(d!=dis[u].w)continue; for(ll i=fir[u];i;i=e[i].nxt){ ll v=e[i].v,uu=e[i].u; if(dis[v].w>dis[uu].w+e[i].w){ dis[v].w=e[i].w+dis[uu].w; q.push((edge){v,dis[v].w}); } } } } bool cmp(node2 a,node2 b){ return a.w<b.w; } int main(){ scanf("%lld%lld",&n,&m); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++)pos[i][j]=inf; for(ll i=1;i<=m;i++){ ll x,y,z; x=read(),y=read(),z=read(); add(x,y,z); add(y,x,z); pos[x][y]=pos[y][x]=min(pos[x][y],z); } dijis(1); //for(int i=1;i<=n;i++)cout<<dis[i].w<<' '; sort(dis,dis+n+1,cmp); ll ans=1; for(int i=2;i<=n;i++){ ll tot=0; for(int j=1;j<i;j++){ ll uu=dis[i].id,vv=dis[j].id; if(dis[i].w==dis[j].w+pos[uu][vv])tot++; } ans=ans*tot%modd; } printf("%lld",ans); return 0; }
其實呢,這個代碼是錯的
別急啊,思路肯定是對的,最短路+不帶合並的生成樹
因為數據範圍小我們可以暴力統計直接使用乘法原理
所以先求出最短路徑dis[i],記錄dis[i[是哪個點的最短路徑id;
把滿足dis[x]=dis[y]+pos[i][j]的一個個點的往生成樹之中加
再根據乘法原理求出答案
然後?
然後就錯了....(霧)
一本通 3.1 例 1」黑暗城堡