zoukankan      html  css  js  c++  java
  • uvalive 3353 Optimal Bus Route Design

    题意:

    给出n个点,以及每个点到其他点的有向距离,要求设计线路使得每一个点都在一个环中,如果设计的线路拥有最小值,那么这个线路就是可选的。输出这个最小值或者说明最小线路不存在。

    思路:

    在DAG的最小路径覆盖中,找到的最大匹配数实际是非终点的点的最大数量(每一个匹配对应一个起点),点数减去这个数量就是终点的最少数量,一个终点对应一条路径,所以这个路径覆盖是最小的。

    这个题要求每一个点都在一个环中,也就是说找到一个设计线路的方案使之不存在DAG,那么自然就没有终点存在,也就意味着每一个点都可以作为起点,即是每一个点都有匹配,那么终点的数量就为0,所以只要这个图存在完美匹配,那么方案就一定存在。

    用匈牙利算法找一下最大匹配,若最大匹配数量为n,那么方案就存在,接下来要找的就是最小的权值,既带权二分图的最小匹配,所以修改KM算法即可。

    复杂度O(n^3)。

    代码:

      1 #include <stdio.h>
      2 #include <string.h>
      3 #include <algorithm>
      4 #include <vector>
      5 using namespace std;
      6 
      7 const int N = 105;
      8 const int inf = 0x3f3f3f3f;
      9 
     10 int match[N],mp[N][N];
     11 int link[N];
     12 bool vis[N];
     13 bool vis_x[N],vis_y[N];
     14 int slack[N];
     15 int lx[N],ly[N];
     16 
     17 vector<int> g[N];
     18 
     19 bool dfs(int u)
     20 {
     21     vis_x[u] = 1;
     22     
     23     for (int j = 0;j < g[u].size();j++)
     24     {
     25         int i = g[u][j];
     26         
     27         if (vis_y[i]) continue;
     28         
     29         int gap = lx[u] + ly[i] - mp[u][i];
     30         
     31         if (gap == 0)
     32         {
     33             vis_y[i] = 1;
     34             
     35             if (match[i] == - 1 || dfs(match[i]))
     36             {
     37                 match[i] = u;
     38                 
     39                 return true;
     40             }
     41         }
     42         else
     43         {
     44             slack[i] = min(gap,slack[i]);
     45         }
     46     }
     47     
     48     return false;
     49 }
     50 
     51 int km(int n)
     52 {
     53     memset(match,-1,sizeof(match));
     54     memset(ly,0,sizeof(ly));
     55     
     56     for (int i = 1;i <= n;i++)
     57     {
     58         lx[i] = mp[i][1];
     59         
     60         for (int j = 2;j <= n;j++)
     61         {
     62             lx[i] = max(lx[i],mp[i][j]);
     63         }
     64     }
     65     
     66     for (int i = 1;i <= n;i++)
     67     {
     68         memset(slack,inf,sizeof(slack));
     69         
     70         while (1)
     71         {
     72             memset(vis_x,0,sizeof(vis_x));
     73             memset(vis_y,0,sizeof(vis_y));
     74             
     75             if (dfs(i)) break;
     76             
     77             int d = inf;
     78             
     79             for (int j = 1;j <= n;j++)
     80             {
     81                 if (!vis_y[j]) d = min(d,slack[j]);
     82             }
     83             
     84             for (int j = 1;j <= n;j++)
     85             {
     86                 if (vis_x[j]) lx[j] -= d;
     87                 if (vis_y[j]) ly[j] += d;
     88             }
     89         }
     90     }
     91     
     92     int ans = 0;
     93     
     94     for (int i = 1;i <= n;i++)
     95     {
     96         ans += mp[match[i]][i];
     97     }
     98     
     99     return ans;
    100 }
    101 
    102 bool dfs2(int u)
    103 {
    104     for (int i = 0;i < g[u].size();i++)
    105     {
    106         int v = g[u][i];
    107         
    108         if (vis[v]) continue;
    109         
    110         vis[v] = 1;
    111             
    112         if (link[v] == -1 || dfs2(link[v]))
    113         {
    114             link[v] = u;
    115             
    116             return true;
    117         }
    118     }
    119     
    120     return false;
    121 }
    122 
    123 bool hungary(int n)
    124 {
    125     memset(link,-1,sizeof(link));
    126     int res = 0;
    127     for (int i = 1;i <= n;i++)
    128     {
    129         memset(vis,0,sizeof(vis));
    130         if (dfs2(i)) res++;
    131     }
    132     
    133     return res >= n;
    134 }
    135 
    136 int main()
    137 {
    138     int n;
    139     
    140     while (scanf("%d",&n) != EOF && n)
    141     {
    142         for (int i = 1;i <= n;i++)
    143         {
    144             for (int j = 1;j <= n;j++)
    145                 mp[i][j] = -inf;
    146         }
    147         
    148         for (int i = 0;i <= n;i++) g[i].clear();
    149         
    150         for (int i = 1;i <= n;i++)
    151         {
    152             int a,b;
    153             
    154             while (scanf("%d",&a) != EOF)
    155             {
    156                 if (a == 0) break;
    157                 
    158                 scanf("%d",&b);
    159                 
    160                 mp[i][a] = -b;
    161                 
    162                 g[i].push_back(a);
    163             }
    164         }
    165         
    166         if (hungary(n))
    167         {
    168             printf("%d
    ",-km(n));
    169         }
    170         else
    171         {
    172             printf("N
    ");
    173         }
    174     }
    175     
    176     return 0;
    177 }
  • 相关阅读:
    【编程思想】【设计模式】【结构模式Structural】适配器模式adapter
    【编程思想】【设计模式】【结构模式Structural】3-tier
    【编程思想】【设计模式】【创建模式creational】原形模式Prototype
    【编程思想】【设计模式】【创建模式creational】Pool
    【编程思想】【设计模式】【创建模式creational】lazy_evaluation
    【编程思想】【设计模式】【创建模式creational】Borg/Monostate
    【编程思想】【设计模式】【创建模式creational】抽象工厂模式abstract_factory
    【编程思想】【设计模式】【创建模式creational】建造者模式builder
    【编程思想】【设计模式】【行为模式Behavioral】策略模式strategy
    【编程思想】【设计模式】【创建模式creational 】工厂模式factory_method
  • 原文地址:https://www.cnblogs.com/kickit/p/8809050.html
Copyright © 2011-2022 走看看