一本通 3.1 例 1」黑暗城堡
描述
你知道黑暗城堡有 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+1,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++;
}
if(tot==0)tot=1;
ans=ans*tot%modd;
}
printf("%lld",ans);
return 0;
}
其实呢,这个代码是错的
别急啊,思路肯定是对的,最短路+不带合并的生成树
因为数据范围小我们可以暴力统计直接使用乘法原理
所以先求出最短路径dis[i],记录dis[i[是哪个点的最短路径id;
把满足dis[x]=dis[y]+pos[i][j]的一个个点的往生成树之中加
再根据乘法原理求出答案
然后?
然后就错了...
9.12 21:36
之前没有来得及填坑,目前已经调出了50分代码emm...已更正
9.12 21:48
已更正完毕,sort的时候没留神从0开始排了....这种错就是难得查啊。
对于以前被坑了的小伙伴们表示深深抱歉。