zoukankan      html  css  js  c++  java
  • 解题:HAOI 2012 道路

    题面

    这题不开O2怎么过=。=

    可能这种有关最短路的计数题做多了就有些感觉了......

    以每个点为基准跑出一张最短路图,然后对每个边$(u,v)$统计两个东西。一个$pre[u]$表示到达$u$这个起点的路径条数,一个$nxt[v]$表示从$v$开始的最短路数,然后对每条边来一下乘法原理。

    然后是这两个玩意的统计方法,$pre[]$可以在最短路图上跑拓扑排序得出,$nxt[]$可以跑记忆化搜索,这样统计的复杂度是$O(n+m)$的,总复杂度大概$O(nmlog$ $n)$?然而并不能卡过去......

      1 // luogu-judger-enable-o2
      2 #include<queue>
      3 #include<cstdio>
      4 #include<cctype>
      5 #include<cstring>
      6 #include<algorithm>
      7 using namespace std;
      8 const int N=1505,M=5005;
      9 const long long mod=1e9+7;
     10 struct a{int node,dist;};
     11 bool operator < (a x,a y)
     12 {
     13     return x.dist>y.dist;
     14 }
     15 priority_queue<a> hp;
     16 int dis[N],vis[N],pre[N],nxt[N],deg[N],ans[M],que[N];
     17 int p[N],noww[M],from[M],goal[M],val[M];
     18 int n,m,t1,t2,t3,cnt,f,b;
     19 inline int read()
     20 {
     21     int ret=0;
     22     char ch=getchar();
     23     while(!isdigit(ch))
     24         ch=getchar();
     25     while(isdigit(ch))
     26         ret=(ret<<3)+(ret<<1)+(ch^48),ch=getchar();
     27     return ret;
     28 }
     29 void link(int f,int t,int v)
     30 {
     31     noww[++cnt]=p[f],p[f]=cnt;
     32     goal[cnt]=t,val[cnt]=v,from[cnt]=f;
     33 } 
     34 void Dijkstra(int s)
     35 {
     36     register int i; 
     37     memset(vis,0,sizeof vis);
     38     memset(dis,0x3f,sizeof dis);
     39     dis[s]=0,hp.push((a){s,0});
     40     while(!hp.empty())
     41     {
     42         a tt=hp.top(); hp.pop(); int tn=tt.node;
     43         if(vis[tn]) continue ; vis[tn]=true;
     44         for(i=p[tn];i;i=noww[i])
     45             if(dis[goal[i]]>dis[tn]+val[i])
     46             {
     47                 dis[goal[i]]=dis[tn]+val[i];
     48                 hp.push((a){goal[i],dis[goal[i]]});
     49             }
     50     }
     51 }
     52 void getpre(int nde)
     53 {
     54     register int i,j;
     55     for(i=1;i<=n;i++)
     56         for(j=p[i];j;j=noww[j])
     57             if(dis[goal[j]]==dis[i]+val[j]) deg[goal[j]]++;
     58     que[f=b=0]=nde,pre[nde]=1;
     59     while(f<=b)
     60     {
     61         int tn=que[f++];
     62         for(i=p[tn];i;i=noww[i])
     63             if(dis[goal[i]]==dis[tn]+val[i])
     64             {
     65                 pre[goal[i]]+=pre[tn];
     66                 if(!(--deg[goal[i]])) que[++b]=goal[i];
     67             }
     68     }    
     69 }
     70 void getnxt(int nde)
     71 {
     72     nxt[nde]=1;
     73     for(int i=p[nde];i;i=noww[i])
     74         if(dis[goal[i]]==dis[nde]+val[i])
     75         {
     76             if(!nxt[goal[i]]) getnxt(goal[i]);
     77             nxt[nde]+=nxt[goal[i]];
     78         } 
     79 }
     80 int main ()
     81 {
     82     register int i,j;
     83     scanf("%d%d",&n,&m);
     84     for(int i=1;i<=m;i++)
     85         scanf("%d%d%d",&t1,&t2,&t3),link(t1,t2,t3);
     86     for(i=1;i<=n;i++) 
     87     {
     88         Dijkstra(i);
     89         memset(pre,0,sizeof pre);
     90         memset(nxt,0,sizeof nxt);
     91         memset(deg,0,sizeof deg);
     92         getpre(i),getnxt(i);
     93         for(j=1;j<=m;j++)
     94             if(dis[from[j]]+val[j]==dis[goal[j]])
     95                 ans[j]+=1ll*pre[from[j]]*nxt[goal[j]]%mod,ans[j]%=mod;
     96     }
     97     for(i=1;i<=m;i++)
     98         printf("%d
    ",ans[i]);
     99     return 0;
    100 }
    View Code
  • 相关阅读:
    hdu 1455 N个短木棒 拼成长度相等的几根长木棒 (DFS)
    hdu 1181 以b开头m结尾的咒语 (DFS)
    hdu 1258 从n个数中找和为t的组合 (DFS)
    hdu 4707 仓鼠 记录深度 (BFS)
    LightOJ 1140 How Many Zeroes? (数位DP)
    HDU 3709 Balanced Number (数位DP)
    HDU 3652 B-number (数位DP)
    HDU 5900 QSC and Master (区间DP)
    HDU 5901 Count primes (模板题)
    CodeForces 712C Memory and De-Evolution (贪心+暴力)
  • 原文地址:https://www.cnblogs.com/ydnhaha/p/9795062.html
Copyright © 2011-2022 走看看