zoukankan      html  css  js  c++  java
  • 洛谷P3953 [NOIP2017]逛公园

    K<=50,感觉可以DP

    先建反图求出从n到各个点的最短路,然后在正图上DP

    设f[当前点][比最短路多走的距离]=方案数

    转移显然是 $f[v][res]=sum f[u][res+tmp]$  tmp是从v到u比最短路多走的路程

    注意如果图中有0环,则有无穷多种方案。

    判0环可以DFS判,也可以把最短路边和0权边建在一个新图上,用拓扑排序判(显然前者更简单)

      1 /*by SilverN*/
      2 #include<iostream>
      3 #include<algorithm>
      4 #include<cstdio>
      5 #include<cmath>
      6 #include<cstring>
      7 #include<queue>
      8 using namespace std;
      9 const int mxn=100010;
     10 int read(){
     11     int x=0,f=1;char ch=getchar();
     12     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     13     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
     14     return x*f;
     15 }
     16 struct edge{
     17     int v,nxt,w;
     18 }e[mxn<<1],er[mxn<<1];
     19 int hd[mxn],mct=0;
     20 int hdr[mxn],rct=0;
     21 void add_edge(int u,int v,int w){
     22     e[++mct].v=v;e[mct].nxt=hd[u];e[mct].w=w;hd[u]=mct;return;
     23 }
     24 void add_edgeR(int u,int v,int w){
     25     er[++rct].v=v;er[rct].nxt=hdr[u];er[rct].w=w;hdr[u]=rct;return;
     26 }
     27 int dis[mxn];
     28 bool inq[mxn];
     29 int vis[mxn];
     30 queue<int>q;
     31 int n,m,K,P;
     32 void SPFA(int s){//反图SPFA 
     33     memset(dis,0x3f,sizeof(dis));
     34     dis[s]=0;
     35     q.push(s);
     36     while(!q.empty()){
     37         int u=q.front();q.pop();inq[u]=0;
     38         for(int i=hdr[u];i;i=er[i].nxt){
     39             int v=er[i].v;
     40             if(dis[v]>dis[u]+er[i].w){
     41                 dis[v]=dis[u]+er[i].w;
     42                 if(!inq[v]){ inq[v]=1;    q.push(v); }
     43             }
     44         }
     45     }
     46     return;
     47 }
     48 inline void add(int &a,int b){
     49     a+=b; a=(a>P)?(a-P):a; return;
     50 }
     51 int f[mxn][51];
     52 int ind[mxn];//时间戳
     53 int cir;
     54 int DP(int u,int res){
     55 //    printf("in:%d %d
    ",u,res);
     56     if(vis[u] && ind[u]==res){cir=1;return 0;}
     57     if(f[u][res]!=-1)return f[u][res];
     58     int tmp=0;
     59     if(u==n && !res)tmp++;//return 1影响判环 
     60     vis[u]++;
     61     ind[u]=res;
     62     //
     63     for(int i=hd[u];i;i=e[i].nxt){
     64         int v=e[i].v;
     65         int x=res-(e[i].w-(dis[u]-dis[v]));
     66         if(x>=0 && x<=K)
     67             add(tmp,DP(v,x));
     68         if(cir)return 0;
     69     }
     70     //
     71     vis[u]--;
     72     ind[u]=0;
     73     return f[u][res]=tmp;
     74 }
     75 void init(){
     76     memset(f,-1,sizeof f);
     77     memset(hd,0,sizeof hd);
     78     memset(hdr,0,sizeof hdr);
     79     memset(ind,0,sizeof ind);
     80     memset(vis,0,sizeof vis);
     81     mct=0;rct=0;cir=0;
     82     return;
     83 }
     84 int main(){
     85     int i,j,u,v,w,ans;
     86     int T=read();
     87     while(T--){
     88         init();
     89         n=read();m=read();K=read();P=read();
     90         for(i=1;i<=m;i++){
     91             u=read();v=read();w=read();
     92             add_edge(u,v,w);
     93             add_edgeR(v,u,w);
     94         }
     95         SPFA(n);
     96         ans=0;
     97         for(i=0;i<=K;i++){
     98             add(ans,DP(1,i));
     99             if(cir)break;
    100         }
    101         if(cir) puts("-1");
    102             else printf("%d
    ",ans);
    103     }
    104     return 0;
    105 }
  • 相关阅读:
    Java学习第六篇:集合类
    Java学习第五篇:二进制(原码 反码 补码),位运算,移位运算,约瑟夫问题
    Java学习第四篇:数组,排序,查找
    Java学习第三篇:类的三大特征,抽象类,接口,final关键字
    Java学习第二篇:类,对象,成员属性,成员方法,构造方法,类变量,类方法
    Java学习第一篇:变量,数据类型,运算符,流程控制(简介)
    (转)学习使用Jmeter做压力测试(三)--数据库测试
    (转)学习使用Jmeter做压力测试(一)--压力测试基本概念
    Xcode-项目模板修改
    过程式编程 drawShapes
  • 原文地址:https://www.cnblogs.com/SilverNebula/p/9211033.html
Copyright © 2011-2022 走看看