标签:div style 覆盖 sign mes 匈牙利算法 最小 tin 最大匹配
题意:
给出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 }
uvalive 3353 Optimal Bus Route Design
标签:div style 覆盖 sign mes 匈牙利算法 最小 tin 最大匹配
原文地址:https://www.cnblogs.com/kickit/p/8809050.html