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\n",-km(n));
169         }
170         else
171         {
172             printf("N\n");
173         }
174     }
175     
176     return 0;
177 }

 

posted @ 2018-04-12 17:17  qrfkickit  阅读(229)  评论(0编辑  收藏  举报