记录编号 314309 评测结果 AAAAAAAAAA
题目名称 [HAOI 2012]道路 最终得分 100
用户昵称 Gravatar小e 是否通过 通过
代码语言 C++ 运行时间 1.579 s
提交时间 2016-10-03 06:29:01 内存使用 0.40 MiB
显示代码纯文本
#include "cstdio"
#include "cstring"
#include "iostream"
#include "queue"
using namespace std;

typedef long long LL;
const int mod = 1000000007;
int n, m;
struct Edge
{
	int from, to, w;
	int next;
}edges[5100];
struct Node
{
	int pos, dist;
	inline Node(const int& a, const int& b)
	{
		pos = a; dist = b;
	}
	inline bool operator < (const Node& a) const
	{
		return dist > a.dist;
	}
};
int head[1600], tot;
int dis[1600];
int in[1600], out[1600], indegree[1600], outdegree[1600];
// in[i]: 最短路径上从起点走到点i的方案数  out[i]: 从i出发的最短路径条数
int ans[5100];

inline void Read(int& a)
{
	a = 0;
	char ch = getchar();
	while(ch < '0' || ch > '9') ch = getchar();
	while(ch >= '0' && ch <= '9'){
		a = a * 10 + ch - '0';
		ch = getchar();
	}
}

inline void AddEdge(const int& from, const int& to, const int& w)
{
	edges[++tot].from = from;
	edges[tot].to = to;
	edges[tot].w = w;
	edges[tot].next = head[from];
	head[from] = tot;
}

inline void Dijkstra(const int& s)
{
	priority_queue <Node> Q;
	memset(dis, 0x3f, sizeof(dis));
	dis[s] = 0;
	Q.push(Node(s, 0));
	while(!Q.empty()){
		Node top = Q.top(); Q.pop();
		int pos = top.pos, dist = top.dist;
		if(dist != dis[pos]) continue;
		for(int i = head[pos]; i; i = edges[i].next){
			int to = edges[i].to, w = edges[i].w;
			if(dis[to] > dis[pos] + w){
				dis[to] = dis[pos] + w;
				Q.push(Node(to, dis[to]));
			}
		}
	}
}

inline void Topo(const int& s)
{
	memset(in, 0, sizeof(in));
	memset(indegree, 0, sizeof(indegree));
	memset(outdegree, 0, sizeof(outdegree));
	queue <int> Q;
	for(int j = 1; j <= m; j++){
		int from = edges[j].from, to = edges[j].to, w = edges[j].w;
		if(dis[to] == dis[from] + w){
			// 第j条边在从i到to的最短路上
			indegree[to]++; outdegree[from]++;
		}
	}
	in[s] = 1;
	Q.push(s);
	while(!Q.empty()){
		int front = Q.front(); Q.pop();
		for(int i = head[front]; i; i = edges[i].next){
			int from = edges[i].from, to = edges[i].to, w = edges[i].w;
			if(dis[to] == dis[from] + w){
				in[to] = (in[to] + in[from]) % mod;
				indegree[to]--;
				if(!indegree[to]) Q.push(to);
			}
		}	
	}
	// printf("s:%d\n", s);
	// for(int i = 1; i <= n; i++)
	// 	printf("in[%d]:%d\n", i, in[i]);
	// puts("");
}

void DFS(const int& a)
{
	if(out[a]) return;
	out[a] = 1;
	for(int i = head[a]; i; i = edges[i].next){
		int from = edges[i].from, to = edges[i].to, w = edges[i].w;
		if(dis[to] == dis[from] + w){
			DFS(to);
			out[a] = (out[a] + out[to]) % mod;
		}
	}
}

int main()
{
#define SUBMIT
#ifdef SUBMIT
	freopen("roadsw.in", "r", stdin); freopen("roadsw.out", "w", stdout);
#endif

	Read(n); Read(m);
	int from, to, w;
	for(int i = 1; i <= m; i++){
		Read(from); Read(to); Read(w);
		AddEdge(from, to, w);
	}

	for(int i = 1; i <= n; i++){
		Dijkstra(i);
		Topo(i);
		memset(out, 0, sizeof(out));
		for(int j = 1; j <= m; j++){
			int from = edges[j].from, to = edges[j].to, w = edges[j].w;
			if(dis[to] == dis[from] + w){
				DFS(to);
				ans[j] = (ans[j] + (LL)(in[from] * out[to])) % mod;
			}
		}
	}

	for(int i = 1; i <= m; i++)
		printf("%d\n", ans[i] % mod);

#ifndef SUBMIT
	printf("\n----------\n");
	getchar(); getchar();
#else
	fclose(stdin); fclose(stdout);
#endif
	return 0;				
}
 /*
	样例输入
	4 4
	1 2 5
	2 3 5
	3 4 5
	1 4 8
	样例输出
	2
	3
	2
	1
 */
 /*
	4 4
	1 2 6
	1 3 2
	3 2 4
	2 4 2 
 */