一本通 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开始排了....这种错就是难得查啊。

对于以前被坑了的小伙伴们表示深深抱歉。

posted @ 2018-09-04 21:53  lisuier  阅读(821)  评论(1编辑  收藏  举报