• [NOIP2017] 逛公园 【最短路】【强连通分量】


    题目分析:

    首先考虑无数条的情况。出现这种情况一定是一条合法路径经过了$ 0 $环中的点。那么预先判出$ 0 $环中的点和其与$ 1 $和$ n $的距离。加起来若离最短路径不超过$ k $则输出$ -1 $,否则这些点必定不被经过,接着dp后效性消失。由于每条边转移了$ k $次它的起点到终点的状态,所以总时间复杂度为$ O(n+mk) $,可以通过所有数据。

    代码:

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstdlib>
      4 #include<cstring>
      5 #include<queue>
      6 #include<vector>
      7 #include<stack>
      8 using namespace std;
      9 
     10 typedef pair<int,int> pr;
     11 
     12 const int maxn = 105000;
     13 
     14 int n,m,k,p;
     15 vector<pair<int,int> > g[maxn],rg[maxn];
     16 vector <int> ng[maxn];
     17 
     18 int dfn[maxn],low[maxn],instack[maxn],scc[maxn],cl;
     19 int f[maxn][52],arr[maxn][52];
     20 stack <int> sta;
     21 
     22 void init(){
     23     memset(dfn,0,sizeof(dfn));
     24     memset(arr,0,sizeof(arr));
     25     memset(low,0,sizeof(low));
     26     memset(instack,0,sizeof(instack));
     27     memset(scc,0,sizeof(scc));
     28     memset(f,0,sizeof(f));
     29     cl = 0;
     30 }
     31 
     32 void tarjan(int now){
     33     low[now] = dfn[now] = ++cl;
     34     sta.push(now);
     35     for(int i=0;i<ng[now].size();i++){
     36     int k = ng[now][i]; if(instack[k]) continue;
     37     if(dfn[k]) { low[now] = min(low[now],dfn[k]); }
     38     else{ tarjan(k); low[now] = min(low[now],low[k]); }
     39     }
     40     if(low[now] == dfn[now]){
     41     stack<int> tpp;int num = 0;
     42     while(true){
     43         int tp = sta.top();sta.pop();tpp.push(tp);num++;
     44         instack[tp] = 1; scc[tp]=1;
     45         if(now == tp) break;
     46     }
     47     if(num == 1) scc[tpp.top()] = 0;
     48     }
     49 }
     50 
     51 void read(){
     52     scanf("%d%d%d%d",&n,&m,&k,&p);
     53     for(int i=1;i<=n;i++) g[i].clear();
     54     for(int j=1;j<=n;j++) ng[j].clear();
     55     for(int j=1;j<=n;j++) rg[j].clear();
     56     for(int i=1;i<=m;i++){
     57     int u,v,w; scanf("%d%d%d",&u,&v,&w);
     58     g[u].push_back(make_pair(v,w));
     59     rg[v].push_back(make_pair(u,w));
     60     if(w == 0) ng[u].push_back(v);
     61     }
     62 }
     63 
     64 int res;
     65 int d[maxn][2];
     66 priority_queue<pr,vector<pr>,greater<pr> > pq;
     67 void solve_dist(){
     68     memset(d,0x3f,sizeof(d));
     69     pq.push(make_pair(0,1));
     70     while(!pq.empty()){
     71     pair<int,int> tp = pq.top();pq.pop();
     72     if(d[tp.second][0] > 1e9) d[tp.second][0] = tp.first;
     73     else continue;
     74     for(int j=0;j<g[tp.second].size();j++){
     75         int nxt = g[tp.second][j].first,data = g[tp.second][j].second;
     76         data += d[tp.second][0];
     77         if(data > d[nxt][0]) continue;
     78         pq.push(make_pair(data,nxt));
     79     }
     80     }
     81     res = d[n][0];
     82     pq.push(make_pair(0,n));
     83     while(!pq.empty()){
     84     pair<int,int> tp = pq.top();pq.pop();
     85     if(d[tp.second][1] > 1e9) d[tp.second][1] = tp.first;
     86     else continue;
     87     for(int j=0;j<rg[tp.second].size();j++){
     88         int nxt = rg[tp.second][j].first,data = rg[tp.second][j].second;
     89         data += d[tp.second][1];
     90         if(data > d[nxt][1]) continue;
     91         pq.push(make_pair(data,nxt));
     92     }
     93     }
     94 }
     95 
     96 void dfs(int now,int lw){
     97     if(arr[now][lw]) return;
     98     int nowd = d[now][0]+lw;arr[now][lw] = 1;
     99     for(int j=0;j<rg[now].size();j++){
    100     int nxt = rg[now][j].first,data = rg[now][j].second;
    101     if(scc[nxt])continue;
    102     int nd = nowd-data; nd -= d[nxt][0];
    103     if(nd < 0) continue;
    104     if(nd > k) continue;
    105     dfs(nxt,nd);
    106     f[now][lw] += f[nxt][nd]; f[now][lw] %= p;
    107     }
    108 }
    109 
    110 void work(){
    111     for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i);
    112     if(scc[1]||scc[n]) {puts("-1");return;}
    113     
    114     solve_dist();
    115     
    116     for(int i=1;i<=n;i++)
    117     if(scc[i]) if(d[i][0]+d[i][1]<=res+k){puts("-1");return;}
    118     
    119     f[1][0] = 1;arr[1][0] = 1;int ans = 0;
    120     for(int i=0;i<=k;i++) {
    121     dfs(n,i);ans += f[n][i]; ans %= p;
    122     }
    123     printf("%d
    ",ans);
    124 }
    125 
    126 int main(){
    127     int t; scanf("%d",&t);
    128     while(t--){ init(); read(); work(); }
    129     return 0;
    130 }
  • 相关阅读:
    储存过程与触发器
    session 和 cookie
    (四)Jira工作流状态的属性
    (三)Jira scriptrunner插件
    (二)JIRA安装
    vs2015 调试无法访问网站的问题
    设计模式
    依赖倒置、反射、泛型、委托、AOP
    C# .NET
    持续集成
  • 原文地址:https://www.cnblogs.com/Menhera/p/9086027.html
Copyright © 2020-2023  润新知