码迷,mamicode.com
首页 > 其他好文 > 详细

[HAOI2012]道路

时间:2017-10-28 11:18:32      阅读:154      评论:0      收藏:0      [点我收藏+]

标签:最短路   评估   --   print   size   标记   blog   std   重要   

题目描述

C国有n座城市,城市之间通过m条[b]单向[/b]道路连接。一条路径被称为最短路,当且仅当不存在从 它的起点到终点的另外一条路径总长度比它小。两条最短路不同,当且仅当它们包含的道路序列不同。我们需要对每条道路的重要性进行评估,评估方式为计算有多 少条不同的最短路经过该道路。现在,这个任务交给了你。

输入输出格式

输入格式:

第一行包含两个正整数n、m

接下来m行每行包含三个正整数u、v、w,表示有一条从u到v长度为w的道路

输出格式:

输出应有m行,第i行包含一个数,代表经过第i条道路的最短路的数目对[b]1000000007取模[/b]后的结果

输入输出样例

输入样例#1: 复制
4 4
1 2 5
2 3 5
3 4 5
1 4 8
输出样例#1: 复制
2
3
2
1

说明

数据规模

30%的数据满足:n≤15、m≤30

60%的数据满足:n≤300、m≤1000

100%的数据满足:n≤1500、m≤5000、w≤10000

以每一个点为起点,做一次SPFA,把在最短路上的边标记

设S到i的路径数cnt1[i],在设i到其他点的最短路数cnt2[i]

因为选出来的边构成的图无环,所以用拓扑排序来递推

cnt1[v]+=cnt1[u]

至于cnt2数组,用逆拓扑序递推

于是一条边(u,v)的ans+=cnt1[u]*cnt2[v]

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<queue>
  6 using namespace std;
  7 struct Node
  8 {
  9   int next,to,dis;
 10 }edge[20001];
 11 int num,head[10001],d[10001];
 12 long long cnt1[10001],cnt2[10001],ans[20001],n,m;
 13 int q[1000001];
 14 bool vis[10001],pd[10001];
 15 long long dist[10001];
 16 int Mod=1000000007;
 17 void add(int u,int v,int d)
 18 {
 19   num++;
 20   edge[num].next=head[u];
 21   head[u]=num;
 22   edge[num].to=v;
 23   edge[num].dis=d;
 24 }
 25 void SPFA(int S)
 26 {queue<int>Q;
 27   int i,j;
 28   memset(pd,0,sizeof(pd));
 29   memset(vis,0,sizeof(vis));
 30   memset(dist,127/3,sizeof(dist));
 31   memset(d,0,sizeof(d));
 32   Q.push(S);
 33   dist[S]=0;
 34   while (Q.empty()==0)
 35     {
 36       int u=Q.front();
 37       Q.pop();
 38       vis[u]=0;
 39       for (i=head[u];i;i=edge[i].next)
 40     {
 41       int v=edge[i].to;
 42       if (dist[v]>dist[u]+edge[i].dis)
 43         {
 44           dist[v]=dist[u]+edge[i].dis;
 45           if (vis[v]==0)
 46         {
 47           vis[v]=1;
 48           Q.push(v);
 49         }
 50         }
 51     }
 52     }
 53   for (i=1;i<=n;i++)
 54     for (j=head[i];j;j=edge[j].next)
 55       if (dist[i]+edge[j].dis==dist[edge[j].to])
 56     pd[j]=1,d[edge[j].to]++;
 57 }
 58 void Top_sort(int S)
 59 {int i,j;
 60   memset(cnt1,0,sizeof(cnt1));
 61   memset(cnt2,0,sizeof(cnt2));
 62   int h=0,t=1;
 63   q[1]=S;
 64   cnt1[S]=1;
 65   while (h<t)
 66     {
 67       h++;
 68       int u=q[h];
 69       for (i=head[u];i;i=edge[i].next)
 70     {
 71       int v=edge[i].to;
 72       if (pd[i])
 73         {
 74           d[v]--;
 75           cnt1[v]+=cnt1[u];
 76           cnt1[v]%=Mod;
 77           if (d[v]==0)
 78         {
 79           t++;
 80           q[t]=v;
 81         }
 82         }
 83     }
 84     }
 85   for (i=t;i>=1;i--)
 86     {
 87       int u=q[i];
 88       cnt2[u]++;
 89       for (j=head[u];j;j=edge[j].next)
 90     if (pd[j])
 91     {
 92       int v=edge[j].to;
 93       cnt2[u]+=cnt2[v];
 94       cnt2[u]%=Mod;
 95     }
 96     }
 97   for (i=1;i<=n;i++)
 98     for (j=head[i];j;j=edge[j].next)
 99       if (pd[j])
100       {
101     int v=edge[j].to;
102     ans[j]+=cnt1[i]*cnt2[v];
103     ans[j]%=Mod;
104       }
105 }
106 int main()
107 {int i,u,v,d;
108   cin>>n>>m;
109   for (i=1;i<=m;i++)
110     {
111       scanf("%d%d%d",&u,&v,&d);
112       add(u,v,d);
113     }
114   for (i=1;i<=n;i++)
115   {
116     SPFA(i);
117     Top_sort(i);
118   }
119   for (i=1;i<=m;i++)
120     printf("%lld\n",ans[i]);
121 }

 

[HAOI2012]道路

标签:最短路   评估   --   print   size   标记   blog   std   重要   

原文地址:http://www.cnblogs.com/Y-E-T-I/p/7745909.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!