zoukankan      html  css  js  c++  java
  • [USACO11JAN]Roads and Planes

    嘟嘟嘟

    这道题他会卡spfa,不过据说加SLF优化后能过,但还是讲讲正解吧。

    题中有很关键的一句,就是无向边都是正的,只有单向边可能会有负的。当把整个图缩点后,有向边只会连接在每一个联通块之间(因为图中没有环),而且缩点后的图一定是一个DAG,DAG的最短路就可以拓扑排序后直接求出最短路。

    因此,对于每一个联通块内,我们可以dijkstra跑最短路:除了常规的更新以外,每一次跑的时候都要先把这个块内的所有点都放进优先队列中,因为有的点可能已经从别的联通块更新了。然后对于一条边u->v,如果u,v在一个联通块内,就正常更新,否则是更新dis[y],不把他放进队列,而是把y所在的联通块的入度--,如果为0,就放进拓扑序的队列中。

    直到拓扑序的队列空。

    对于有些走不到的点,可能在INF上加上了一个负数,因此最后判断是否能走到不能dis[i] = INF?,我就是稍微把这个上界放小一点,但又大于最远的dis,于是判断dis[i] > INF / 2?。

      1 #include<cstdio>
      2 #include<iostream>
      3 #include<cmath>
      4 #include<algorithm>
      5 #include<cstring>
      6 #include<cstdlib>
      7 #include<cctype>
      8 #include<vector>
      9 #include<stack>
     10 #include<queue>
     11 using namespace std;
     12 #define enter puts("") 
     13 #define space putchar(' ')
     14 #define Mem(a) memset(a, 0, sizeof(a))
     15 typedef long long ll;
     16 typedef double db;
     17 const int INF = 0x3f3f3f3f;
     18 const db eps = 1e-8;
     19 const int maxn = 2.5e4 + 5;
     20 inline ll read()
     21 {
     22     ll ans = 0;
     23     char ch = getchar(), last = ' ';
     24     while(!isdigit(ch)) {last = ch; ch = getchar();}
     25     while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();}
     26     if(last == '-') ans = -ans;
     27     return ans;
     28 }
     29 inline void write(ll x)
     30 {
     31     if(x < 0) x = -x, putchar('-');
     32     if(x >= 10) write(x / 10);
     33     putchar(x % 10 + '0');
     34 }
     35 
     36 int n, r, p, s;
     37 vector<int> v[maxn], c[maxn];
     38 vector<int> blo[maxn];
     39 
     40 int col[maxn], cnt = 0;
     41 void dfs(int now)
     42 {
     43     col[now] = cnt; blo[cnt].push_back(now);
     44     for(int i = 0; i < (int)v[now].size(); ++i)
     45         if(!col[v[now][i]]) dfs(v[now][i]);
     46 }
     47 
     48 int in[maxn];
     49 queue<int> topo;
     50 
     51 #define pr pair<int, int>
     52 #define mp make_pair
     53 int dis[maxn];
     54 bool inq[maxn];
     55 void dijkstra(int bl)
     56 {
     57     Mem(inq);
     58     priority_queue<pr, vector<pr>, greater<pr> > q;
     59     for(int i = 0; i < (int)blo[bl].size(); ++i) q.push(mp(dis[blo[bl][i]], blo[bl][i]));
     60     while(!q.empty())
     61     {
     62         int now = q.top().second; q.pop();
     63         if(inq[now]) continue;
     64         inq[now] = 1;
     65         for(int i = 0; i < (int)v[now].size(); ++i)
     66         {
     67             int to = v[now][i];
     68             if(col[now] == col[to])
     69             {
     70                 if(dis[to] > dis[now] + c[now][i])
     71                 {
     72                     dis[to] = dis[now] + c[now][i];
     73                     q.push(mp(dis[to], to));
     74                 }
     75             }
     76             else
     77             {
     78                 if(dis[to] > dis[now] + c[now][i]) dis[to] = dis[now] + c[now][i];
     79                 if(!--in[col[to]]) topo.push(col[to]);
     80             }
     81         }
     82     }
     83 }
     84 
     85 int main()
     86 {
     87     n = read(); r = read(); p = read(); s = read();
     88     for(int i = 1; i <= r; ++i)
     89     {
     90         int x = read(), y = read(), co = read();
     91         v[x].push_back(y); c[x].push_back(co);
     92         v[y].push_back(x); c[y].push_back(co);
     93     }
     94     for(int i = 1; i <= n; ++i) if(!col[i]) ++cnt, dfs(i);
     95     for(int i = 1; i <= p; ++i)
     96     {
     97         int x = read(), y = read(), co = read();
     98         v[x].push_back(y); c[x].push_back(co);
     99         if(col[x] != col[y]) in[col[y]]++;
    100     }
    101     for(int i = 0; i <= cnt; ++i) if(!in[i]) topo.push(i);
    102     for(int i = 1; i <= n; ++i) dis[i] = INF; dis[s] = 0;
    103     while(!topo.empty()) dijkstra(topo.front()), topo.pop();
    104     for(int i = 1; i <= n; ++i) dis[i] > (INF >> 1) ? printf("NO PATH
    ") : (write(dis[i]), enter);
    105     return 0;
    106 }
    View Code
  • 相关阅读:
    14.挂载硬件设备
    13.Linux文件存储系统
    12.su 命令与sudo 服务
    11.文件访问控制列表
    10. 文件权限与归属
    9. Linux用户身份和能力
    8. Linux重要的环境变量
    7. Linux命令行的通配符、转义字符
    6. Linux输入输出重定向
    5. Linux文件目录管理和打包压缩与搜索命令
  • 原文地址:https://www.cnblogs.com/mrclr/p/9600698.html
Copyright © 2011-2022 走看看