zoukankan      html  css  js  c++  java
  • bzoj 2750: [HAOI2012]Road

    Description

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

    Input

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

    Output

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

    Sample Input

    4 4
    1 2 5
    2 3 5
    3 4 5
    1 4 8

    Sample Output

    2
    3
    2
    1

    HINT

    数据规模

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

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

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

    Source

    社交网络的加强版。floyd肯定是跑不过了。

    首先枚举一个起点开始跑spfa,然后在最短路图上统计答案,(最短路图是DAG)

    对于一条在最短路图上的边(x.y),被经过次数是(源点到x的方案数)*(y的后继结点个数)。。。

    这个很显然,然后因为是DAG这两个值可以通过拓扑排序或记忆化搜索来解决。

    // MADE BY QT666
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<iostream>
    #include<cstring>
    #include<vector>
    #include<queue>
    using namespace std;
    typedef long long ll;
    const int N=100050;
    const int Mod=1000000007;
    int head[N],to[N],nxt[N],v[N],cnt,n,m;
    ll ans[N],dp[N],dp2[N],dis[N],vis[N],du[N];
    struct data{
      int x,y,w;
    }e[N];
    struct Data{
      int x,w;
    };
    vector<Data> p[N];
    void lnk(int x,int y,int z){
      to[++cnt]=y,nxt[cnt]=head[x],v[cnt]=z,head[x]=cnt;
      p[y].push_back((Data){x,z});
    }
    queue<int> Q;
    void spfa(int s){
      for(int i=1;i<=n;i++) dis[i]=19260817,vis[i]=0;
      Q.push(s);vis[s]=1;dis[s]=0;
      while(!Q.empty()){
        int x=Q.front();Q.pop();vis[x]=0;
        for(int i=head[x];i;i=nxt[i]){
          int y=to[i];
          if(dis[y]>dis[x]+v[i]){
    	dis[y]=dis[x]+v[i];
    	if(!vis[y]) Q.push(y),vis[y]=1;
          }
        }
      }
    }
    int dfs1(int x){
      if(dp[x]) return dp[x];
      for(int i=0;i<p[x].size();i++){
        int y=p[x][i].x;
        if(dis[y]==dis[x]-p[x][i].w){du[y]++;(dp[x]+=dfs1(y))%=Mod;}
      }
      return dp[x];
    }
    void topsort(){
      for(int i=1;i<=n;i++) if(du[i]==0) Q.push(i);
      while(!Q.empty()){
        int x=Q.front();Q.pop();
        for(int i=0;i<p[x].size();i++){
          int y=p[x][i].x;
          if(dis[y]==dis[x]-p[x][i].w){
    	du[y]--;dp2[y]+=dp2[x];
    	if(du[y]==0) Q.push(y);
          }
        }
      }
    }
    int main(){
      freopen("roadsw.in","r",stdin);
      freopen("roadsw.out","w",stdout);
      scanf("%d%d",&n,&m);
      for(int i=1;i<=m;i++){
        scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].w);
        lnk(e[i].x,e[i].y,e[i].w);
      }
      for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++) dp[j]=dp2[j]=0,du[j]=0;
        spfa(i);
        dp[i]=1;for(int j=1;j<=n;j++) dp[j]=dfs1(j);
        for(int j=1;j<=n;j++) dp2[j]=1;topsort();
        for(int j=1;j<=m;j++) if(dis[e[j].x]+e[j].w==dis[e[j].y]) (ans[j]+=dp[e[j].x]*dp2[e[j].y])%=Mod;
      }
      for(int i=1;i<=m;i++) printf("%lld
    ",ans[i]);
      return 0;
    }
    

      

  • 相关阅读:
    转 mysql 数据结构详解
    转单元测试之道C#版
    转 告诉你如何用C#写出iOS与Android应用
    转 MySQL索引背后的数据结构及算法原理
    转单元测试基础知识
    转C#冒泡排序
    如何让web页面鼠标右键单击之后不出现菜单选项
    开博文
    jquery ui 1.7 ui.tabs 动态添加与关闭(按钮关闭+双击关闭)
    jquery ui tabs详解(中文)
  • 原文地址:https://www.cnblogs.com/qt666/p/7427895.html
Copyright © 2011-2022 走看看