zoukankan      html  css  js  c++  java
  • [题解]UVA10917 Walk Through the Forest

    #1.0 理解题意

    本题最需要理解的是这句话:

    如果有一条从B到他的家的路线比从A到他的家的任何可能的路线都短,那么他认为从A到B更好。

    (d_x) 表示 (x)(2) 号节点的最短路,那么上文的意思就是如果 (A,B) 间存在道路且 (d_B<d_A),那么道路 (A o B) 便是一种可行的选择。

    #2.0 大体思路

    根据上面那句话,我们便需要先处理出所有点到 (2) 号点的最短距离。然后按照上面的要求重新建图,这里建出的边是单向边,再注意到得到的图是一张有向无环图( exttt{DAG})),因为每条边的边权都是非负数,用反证法不难证明得到的最短路图不存在环。

    此时考虑 ( exttt{DAG}) 上的动态规划,设 (sum_x) 表示从 (1) 号节点到 (x) 号节点可行的路径条数,显然有

    [sum_x=sumlimits_{(y,x)in E}sum_y. ]

    这里 (E) 表示边集,有序数对 ((u,v)) 表示一条从 (u)(v) 的有向边。边界为 (sum_1=1.)

    同时注意到,节点 (1) 不一定是入度为 (0) 的点,入度为零的点除 (1) 外不会对答案造成贡献。

    拓扑结束后得到的结果便是本题所求。

    #define pii pair<int, int>
    #define mp(a, b) make_pair(a, b)
    #define mset(l, x) memset(l, x, sizeof(l))
    
    const int N = 100010;
    const int INF = 0x7fffffff;
    
    struct Edge {
        int u, v, w;
        int nxt;
    };
    Edge e[N], ne[N];
    
    int cnt = 1, ncnt = 1, head[N], nhead[N];
    int dist[N], vis[N], tot[N], s, t, icnt[N];
    int qx[N], frt, tal, tag[N], n, m;
    
    priority_queue <pii > q;
    
    inline void add(const int &u, const int &v, const int &w) {
        e[cnt].u = u, e[cnt].v = v, e[cnt].w = w;
        e[cnt].nxt = head[u], head[u] = cnt ++;
    }
    
    inline void addn(const int &u, const int &v) {
        ne[ncnt].u = u, ne[ncnt].v = v, icnt[v] ++;
        ne[ncnt].nxt = nhead[u], nhead[u] = ncnt ++;
    }
    
    void Dijkstra() {
        mset(dist, 0x3f);
        q.push(mp(0,2)); dist[2] = 0;
        while (q.size()) {
            int now = q.top().second; q.pop();
            if (vis[now]) continue;
            vis[now] = true;
            for (int i = head[now]; i; i = e[i].nxt)
              if (dist[e[i].v] > dist[now] + e[i].w) {
                  dist[e[i].v] = dist[now] + e[i].w;
                  q.push(mp(-dist[e[i].v], e[i].v));
              }
        }
    }
    
    inline void clear() {
        frt = 0, tal = -1; 
        ncnt = cnt = 1; mset(tot, 0);
        mset(icnt, 0); mset(tag, 0);
        mset(vis, 0); mset(dist, 0x3f);
        mset(head, 0); mset(nhead, 0);
    }
    
    void topo() {
        mset(vis, 0);
        for (int i = 1; i <= n; i ++) 
          if (!icnt[i] || i == 1) qx[++ tal] = i;
        tag[1] = tot[1] = vis[1] = 1;
        while (frt <= tal) {
            int now = qx[frt ++];
            for (int i = nhead[now]; i;i = ne[i].nxt) {
                icnt[ne[i].v] --;
                if (tag[now]) {
                    tot[ne[i].v] += tot[now], 
                    tag[ne[i].v] |= tag[now];
                }
                if (!icnt[ne[i].v] && !vis[ne[i].v]) {
                    qx[++ tal] = ne[i].v;
                    vis[ne[i].v] == true;
                }
            }
        }
    }
    
    int main() {
        scanf("%d", &n);
        while (n) {
            scanf("%d", &m); s = 1, t = 2; clear();
            for (int i = 1; i <= m; i ++) {
                int u, v, w; scanf("%d%d%d", &u, &v, &w);
                add(u, v, w); add(v, u, w);
            }
            Dijkstra();
            for (int i = 1; i <= n; i ++)
              for (int j = head[i]; j; j = e[j].nxt)
                if (dist[i] > dist[e[j].v])
                  addn(i, e[j].v);
            topo();
            printf("%d
    ", tot[t]);
            scanf("%d", &n);
        }
        return 0;
    }
    

    End

    希望能为各位带来帮助。

  • 相关阅读:
    keras 与tensorflow 混合使用
    卷积神经网络入门
    Linux Shell
    使用Keras编写GAN的入门
    Wasserstein距离 和 Lipschitz连续
    keras与sklearn的结合使用
    keras与tensorboard结合使用
    【转】java 高并发 基础知识
    用python写map reduce程序
    【转】互联网时代的社会语言学:基于SNS的文本数据挖掘
  • 原文地址:https://www.cnblogs.com/Dfkuaid-210/p/UVA10917.html
Copyright © 2011-2022 走看看