洛谷2505 [HAOI2012]道路(最短路计数)

洛谷传送门

【题目分析】

线段树?bczd,这么小的范围直接暴力就行啦。

直接O(n)枚举源点,每次跑最短路,然后对于每一条路径统计是否在最短路上、两个端点各有多少条最短路径经过即可。

【代码~】

#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e3+510;
const int MAXM=1e4+10;
const int INF=0x3f3f3f3f;
const int MOD=1e9+7;

int n,m,cnt;
int head[MAXN],dis[MAXN],vis[MAXN];
int nxt[MAXM],from[MAXM],to[MAXM],w[MAXM];
int dp1[MAXN],dp2[MAXN];
int du[MAXN];
int ans[MAXM];

int Read(){
	int i=0,f=1;
	char c;
	for(c=getchar();(c>'9'||c<'0')&&c!='-';c=getchar());
	if(c=='-')
	  f=-1,c=getchar();
	for(;c>='0'&&c<='9';c=getchar())
	  i=(i<<3)+(i<<1)+c-'0';
	return i*f;
}

void add(int x,int y,int z){
	nxt[cnt]=head[x];
	head[x]=cnt;
	from[cnt]=x;
	to[cnt]=y;
	w[cnt]=z;
	cnt++;
}

void SPFA(int s){
	queue<int> q;
	memset(dis,INF,sizeof(dis));
	memset(vis,0,sizeof(vis));
	memset(du,0,sizeof(du));
	memset(dp1,0,sizeof(dp1));
	memset(dp2,0,sizeof(dp2));
	dis[s]=0;
	vis[s]=1;
	q.push(s);
	while(!q.empty()){
		int u=q.front();
		q.pop();
		vis[u]=0;
		for(int i=head[u];i!=-1;i=nxt[i]){
			int v=to[i];
			if(dis[v]>dis[u]+w[i]){
				dis[v]=dis[u]+w[i];
				if(!vis[v]){
					vis[v]=1;
					q.push(v);
				}
			}
		}
	}
	for(int i=0;i<cnt;++i){
		int u=from[i],v=to[i];
		if(dis[v]==dis[u]+w[i]){
		  	du[v]++;
		}
	}
}

void bfs(int s){
	queue<int> q;
	q.push(s);
	dp1[s]=1;
	while(!q.empty()){
		int u=q.front();
		q.pop();
		for(int i=head[u];i!=-1;i=nxt[i]){
			int v=to[i];
			if(dis[v]==dis[u]+w[i]){
				dp1[v]=(dp1[v]+dp1[u])%MOD;
				if(!--du[v]){
					q.push(v);
				}
			}
		}
	}
}

int dfs(int u){
	if(dp2[u])
	  return dp2[u];
	dp2[u]=1;
	for(int i=head[u];i!=-1;i=nxt[i]){
		int v=to[i];
		if(dis[v]==dis[u]+w[i]){
			dp2[u]=(dp2[u]+dfs(v))%MOD;
		}
	}
	return dp2[u];
}

int main(){
	memset(head,-1,sizeof(head));
	n=Read(),m=Read();
	for(int i=1;i<=m;++i){
		int x=Read(),y=Read(),z=Read();
		add(x,y,z);
	}
	for(int i=1;i<=n;++i){
		SPFA(i);
		bfs(i);
		dfs(i);
		for(int j=0;j<cnt;++j){
			int u=from[j],v=to[j];
			if(dis[u]+w[j]==dis[v]){
				ans[j]=(ans[j]+(long long)(dp1[u]*dp2[v])%MOD)%MOD;
			}
		}
	}
	for(int i=0;i<cnt;++i)
	  cout<<ans[i]<<'\n';
	return 0;
}

 

posted @ 2018-11-28 16:57  Ishtar~  阅读(114)  评论(0编辑  收藏  举报