• 解题: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
  • 相关阅读:
    渗透利器-kali工具 (第四章-4) 学习python强大的第三方库
    渗透利器-kali工具 (第四章-3) Python数据结构学习
    渗透利器-kali工具 (第四章-2) python循环判断分支语句与异常处理
    渗透利器-kali工具 (第四章-1) Python环境安装与基本语法
    渗透利器-kali工具 (第三章-7) webshell管理工具
    渗透利器-kali工具 (第三章-6) Xss漏洞学习之-Beef-Xss
    php面试笔记(6)-php基础知识-正则表达式考点
    php利用七牛云的对象存储完成图片上传-高效管理图片
    将Markdown编辑器搬进您的博客-让我们更优雅的书写文章
    踩坑ThinkPHP5之模型对象返回的数据集如何转为数组
  • 原文地址:https://www.cnblogs.com/ydnhaha/p/9795062.html
Copyright © 2020-2023  润新知