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;
    }
    

      

  • 相关阅读:
    关于求 p_i != i and p_i != i+1 的方案数的思考过程
    poj 3041 Asteroids 二分图最小覆盖点
    poj 1325 Machine Schedule 最小顶点覆盖
    poj 1011 Sticks 减枝搜索
    poj 1469 COURSES 最大匹配
    zoj 1516 Uncle Tom's Inherited Land 最大独立边集合(最大匹配)
    Path Cover (路径覆盖)
    hdu 3530 SubSequence TwoPoint单调队列维护最值
    zoj 1654 Place the Rebots 最大独立集转换成二分图最大独立边(最大匹配)
    poj 1466 Girls and Boys 二分图最大独立子集
  • 原文地址:https://www.cnblogs.com/qt666/p/7427895.html
Copyright © 2011-2022 走看看