zoukankan      html  css  js  c++  java
  • Codeforces 543B Destroying Roads(最短路)

    题意:

      给定一个n个点(n<=3000)所有边长为1的图,求最多可以删掉多少条边后,图满足s1到t1的距离小于l1,s2到t2的距离小于l2。


    Solution:

      首先可以分两种情况讨论:

        1:假设最后留下的边是互不相交的两条路径。此时的答案是n-s1到t1的最短路径-s2到t2的最短路径。

               2:假设最后留下的边有重合的一段,此时只要枚举重合的这一段的起点和终点,就可以判断。注意此时要考虑这两条路径经过枚举的两点的顺序。

       

         限制的条件比较多,可以用来剪枝的条件也很多。

         由于所有边的长度为1,用DFS或者SPFA算法可以很快地求出最短路。

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N = 3009;
    
    struct edge {
        int v, ne;
    } E[N * N << 1];
    int head[N], cnt;
    
    int n, m, ans;
    int s1, s2, t1, t2, l1, l2;
    
    int dis[5][N];
    int vis[N];
    
    void SPFA (int S, int k) {
        queue<int> q;
        memset (vis, 0, sizeof vis);
        dis[k][S] = 0;
        vis[S] = 1;
        q.push (S);
        while (!q.empty() ) {
            int u = q.front(); q.pop();
            for (int i = head[u]; i; i = E[i].ne) {
                int v = E[i].v;
                if (dis[k][u] + 1 < dis[k][v]) {
                    dis[k][v] = dis[k][u] + 1;
                    if (!vis[v]) {
                        vis[v] = 1;
                        q.push (v);
                    }
                }
            }
            vis[u] = 0;
        }
    }
    
    inline void  add (int u, int v) {
        E[++cnt].v = v, E[cnt].ne = head[u];
        head[u] = cnt;
    }
    
    int main() {
        ios::sync_with_stdio (0);
        cin >> n >> m;
        for (int i = 1, u, v; i <= m; ++i) {
            cin >> u >> v;
            add (u, v), add (v, u);
        }
        cin >> s1 >> t1 >> l1;
        cin >> s2 >> t2 >> l2;
        memset (dis, 0x1f, sizeof dis);
        SPFA (s1, 0);
        SPFA (s2, 1);
        SPFA (t1, 2);
        SPFA (t2, 3);
        if (dis[0][t1] <= l1 && dis[1][t2] <= l2) {
            ans = dis[0][t1] + dis[1][t2];
            for (int i = 1; i <= n; ++i) {
                int flag = 0;
                for (int k = 1; k <= n; ++k) dis[4][k] = 33333;
                for (int j = i + 1; j <= n; ++j) {
                    int tem1 = min (dis[0][i] + dis[2][j], dis[0][j] + dis[2][i]);
                    int tem2 = min (dis[1][i] + dis[3][j], dis[1][j] + dis[3][i]);
                    if (tem1 + tem2 < ans && tem1 < l1 && tem2 < l2) {
                        if (!flag) {
                            SPFA (i, 4);
                            flag = 1;
                        }
                        if (tem1 + dis[4][j] <= l1 && tem2 + dis[4][j] <= l2) {
                            ans = min (ans, tem1 + tem2 + dis[4][j]);
                        }
                    }
                }
            }
        }
        else {
            ans = m + 1;
        }
        cout << m - ans << endl;
    }
    View Code
  • 相关阅读:
    vs 2015 安装
    NPOI封装
    c#事件求解
    一个ERP系统的磕磕碰碰
    谁动了我的产品
    MVC Sesion丢失问题
    设计模式之类关系
    免费的SqlServer优化辅助工具:SqlOptimize (原创)
    Entity Framework Linq 简单笔记
    RhinoMocks简单范例
  • 原文地址:https://www.cnblogs.com/keam37/p/4515508.html
Copyright © 2011-2022 走看看