• Codeforces Round #302 (Div. 2) D. Destroying Roads 最短路 删边


    题目:有n个城镇,m条边权为1的双向边让你破坏最多的道路,使得从s1到t1,从s2到t2的距离分别不超过d1和d2。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <cmath>
    #include <vector>
    #include <queue>
    #include <stack>
    #include <map>
    #include <algorithm>
    #include <set>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long Ull;
    #define MM(a,b) memset(a,b,sizeof(a));
    const double eps = 1e-10;
    const int  inf =0x7f7f7f7f;
    const double pi=acos(-1);
    const int maxn=3000;
    
    vector<int> G[maxn+5];
    int n,m,used[maxn+10],dist[maxn+10][maxn+10],vis[maxn+10];
    
    void bfs(int s)
    {
         MM(used,0);
         MM(vis,0);
         fill(dist[s]+1,dist[s]+n+1,inf);
    
         queue<int> q;
         q.push(s);
         dist[s][s]=0;
         used[s]=1;
         vis[s]=1;
    
         while(q.size())
         {
             int u=q.front();q.pop();
             used[u]=1;
             for(int i=0;i<G[u].size();i++)
             {
                 int v=G[u][i];
                 if(used[v]) continue;
                 dist[s][v]=min(dist[s][v],dist[s][u]+1);
                 if(!vis[v])  {q.push(v);vis[v]=1;}
             }
         }
    }
    
    int main()
    {
        while(~scanf("%d %d",&n,&m))
        {
            for(int i=1;i<=n;i++) G[i].clear();
            for(int i=1;i<=m;i++)
            {
                int u,v;
                scanf("%d %d",&u,&v);
                G[u].push_back(v);
                G[v].push_back(u);
            }
    
            int s1,t1,l1,s2,t2,l2;
            scanf("%d %d %d %d %d %d",&s1,&t1,&l1,&s2,&t2,&l2);
            for(int i=1;i<=n;i++)
                bfs(i);
    
            if(dist[s1][t1]>l1||dist[s2][t2]>l2)
            {
                printf("-1
    ");
                continue;
            }
    
            int ans=dist[s1][t1]+dist[s2][t2];
            for(int u=1;u<=n;u++)
               for(int v=1;v<=n;v++)
               {
                  if(dist[s1][u]+dist[u][v]+dist[v][t1]<=l1&&dist[s2][u]+dist[u][v]+dist[v][t2]<=l2)
                     ans=min(ans,dist[s1][u]+dist[u][v]+dist[v][t1]+dist[s2][u]+dist[v][t2]);
    
                  if(dist[s1][u]+dist[u][v]+dist[v][t1]<=l1&&dist[s2][v]+dist[v][u]+dist[u][t2]<=l2)
                     ans=min(ans,dist[s1][u]+dist[u][v]+dist[v][t1]+dist[s2][v]+dist[u][t2]);
    
               }
               printf("%d
    ",m-ans);
        }
        return 0;
    }
    

      分析:

    1.反过来思考,转换为求s1到t1和s2到t2的最短路。

    2.假如上述两条最短路没有公共边,那么显然能删除的边就是除这两条路以外的所有的边;

    但是假如有重合的边呢?那么我们只需要暴力枚举可能在哪一段重合就好,核心是要让这两条最短路

    总共占据的边数尽可能少,这样删除的边才会尽可能多。

  • 相关阅读:
    面试知识点2
    面试知识点3
    面试知识记录
    JQuery手写一个简单的轮播图
    推荐一款好用的日历插件
    JQuery获取复选框的值
    JQuery手写一个简单的分页
    JQuery给一个元素绑定两次点击事件(第二次点击事件)
    懒加载预加载(图片)
    JQuery Ajax 使用FormData上传文件对象
  • 原文地址:https://www.cnblogs.com/smilesundream/p/5451940.html
Copyright © 2020-2023  润新知