zoukankan      html  css  js  c++  java
  • [NOIp2017提高组]逛公园

    题目大意:
      给你一个有向图,若用dis(u,v)表示从u到v的最短路长度,求从1到n的长度不超过dis(1,n)+k的路径数。

    思路:
      首先分别预处理出以1,n为起点的单、源最短路。
      对于合法的边重构图,然后拓扑排序判环,
      BFS时判断一下当前点是否在合法路径上,
      如果最后一个点没有被搜到且在合法路径上,那么肯定是一个0环。
      最后动态规划,f[i][j]表示长度为dis(1,i)+j的路径数量。

      1 #include<queue>
      2 #include<cstdio>
      3 #include<cctype>
      4 #include<vector>
      5 #include<cstring>
      6 #include<algorithm>
      7 #include<functional>
      8 #include<ext/pb_ds/priority_queue.hpp>
      9 inline int getint() {
     10     register char ch;
     11     while(!isdigit(ch=getchar()));
     12     register int x=ch^'0';
     13     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
     14     return x;    
     15 }
     16 const int inf=0x7fffffff;
     17 const int N=100001,LIM=51;
     18 int n,m,lim,mod;
     19 struct Edge {
     20     int to,w;
     21 };
     22 std::vector<Edge> e0[N],e1[N];
     23 inline void add_edge(const int &u,const int &v,const int &w) {
     24     e0[u].push_back((Edge){v,w});
     25     e1[v].push_back((Edge){u,w});
     26 }
     27 struct Vertex {
     28     int id,dis;
     29     bool operator > (const Vertex &another) const {
     30         return dis>another.dis;
     31     }
     32 };
     33 int dis0[N],dis1[N];
     34 inline void dijkstra(const int &s,int dis[],const std::vector<Edge> e[]) {
     35     static __gnu_pbds::priority_queue<Vertex,std::greater<Vertex> > q;
     36     static __gnu_pbds::priority_queue<Vertex,std::greater<Vertex> >::point_iterator p[N];
     37     for(register int i=1;i<=n;i++) {
     38         p[i]=q.push((Vertex){i,dis[i]=i==s?0:inf});
     39     }
     40     while(!q.empty()&&q.top().dis!=inf) {
     41         const int x=q.top().id;
     42         q.pop();
     43         for(register unsigned i=0;i<e[x].size();i++) {
     44             const int &y=e[x][i].to,&w=e[x][i].w;
     45             if(dis[x]+w<dis[y]) {
     46                 q.modify(p[y],(Vertex){y,dis[y]=dis[x]+w});
     47             }
     48         }
     49     }
     50     while(!q.empty()) q.pop();
     51 }
     52 std::vector<int> top;
     53 inline bool check() {
     54     static int deg[N];
     55     static std::queue<int> q;
     56     memset(deg,0,sizeof deg);
     57     for(register int x=1;x<=n;x++) {
     58         for(register unsigned i=0;i<e0[x].size();i++) {
     59             const int &y=e0[x][i].to,&w=e0[x][i].w;
     60             if(dis0[x]+w==dis0[y]) deg[y]++;
     61         }
     62     }
     63     for(register int x=1;x<=n;x++) {
     64         if(!deg[x]) q.push(x);
     65     }
     66     while(!q.empty()) {
     67         const int x=q.front();
     68         q.pop();
     69         top.push_back(x);
     70         for(register unsigned i=0;i<e0[x].size();i++) {
     71             const int &y=e0[x][i].to,&w=e0[x][i].w;
     72             if(dis0[x]+w!=dis0[y]) continue;
     73             if(!--deg[y]) q.push(y);
     74         }
     75     }
     76     for(register int x=1;x<=n;x++) {
     77         if(deg[x]&&dis0[x]+dis1[x]<=dis0[n]+lim) return false;
     78     }
     79     return true;
     80 }
     81 inline int calc() {
     82     static int f[N][LIM];
     83     memset(f,0,sizeof f);
     84     f[1][0]=1;
     85     for(register int k=0;k<=lim;k++) {
     86         for(register unsigned i=0;i<top.size();i++) {
     87             const int &x=top[i];
     88             if(!f[x][k]) continue;
     89             for(register unsigned i=0;i<e0[x].size();i++) {
     90                 const int &y=e0[x][i].to,&w=e0[x][i].w;
     91                 if(dis0[x]+k+w<=dis0[y]+lim) {
     92                     (f[y][dis0[x]+k+w-dis0[y]]+=f[x][k])%=mod;
     93                 }
     94             }
     95         }
     96     }
     97     int ans=0;
     98     for(register int i=0;i<=lim;i++) {
     99         ans=(ans+f[n][i])%mod;
    100     }
    101     return ans;
    102 }
    103 inline void reset() {
    104     for(register int i=1;i<=n;i++) {
    105         e0[i].clear();
    106         e1[i].clear();
    107     }
    108     top.clear();
    109 }
    110 int main() {
    111     for(register int T=getint();T;T--) {
    112         n=getint(),m=getint(),lim=getint(),mod=getint();
    113         while(m--) {
    114             const int u=getint(),v=getint(),w=getint();
    115             add_edge(u,v,w);
    116         }
    117         dijkstra(1,dis0,e0);
    118         dijkstra(n,dis1,e1);
    119         printf("%d
    ",check()?calc():-1);
    120         reset();
    121     }
    122     return 0;
    123 }
  • 相关阅读:
    最新iOS发布App Store详细图文教程~
    介绍一个轻量级iOS安全框架:SSKeyChain
    今天科普一下 苹果开发者账号中:个人、公司、企业账号的区别
    iOS开发:Framework的创建
    JMS 在 SpringBoot 中的使用
    iOS 引入外部字体 otf/ttf/ttc
    公司企业苹果开发者账号中个人、公司企业账号的不同
    Git版本管理
    有关苹果手机下载应用后提示不受信任的企业开发者解决方案:
    尝试一下markdown
  • 原文地址:https://www.cnblogs.com/skylee03/p/7892282.html
Copyright © 2011-2022 走看看