• [HAOI2012]道路


    题目描述

    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
    ",ans[i]);
    121 }
  • 相关阅读:
    设计模式外观模式
    SQL Server高级查询
    电脑双屏下如何设置程序在第二屏幕运行
    Vistual Studio自带的计划任务功能
    SQL Server定时创建动态表
    访问网站出现空白页面的原因和解决方法
    微软老将Philip Su的离职信:回首12年职场生涯的心得和随笔
    SQL Server更改字段名
    刷新本页与父页的两条代码
    色彩感情
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/7745909.html
Copyright © 2020-2023  润新知