您的位置:首页 > 其它

CodeForcesGym 100641E Inspectors

2015-08-25 20:33 274 查看

Inspectors

Time Limit: 1000ms
Memory Limit: 262144KB
This problem will be judged on CodeForcesGym. Original ID: 100641E
64-bit integer IO format: %I64d Java class name: (Any)

Yuri is a rich business owner. His company has factories in many cities across Russia, all of which need regular, monthly inspections. Now Yuri not only has a large portfolio, but a large family as well and he would like to see some of his children start to learn how the business is run. He gures the best way to do this is to have them perform the factory inspections, but he has two concerns. First, he wants each child to be assigned at least two di erent factories { that way they will be able to compare di erent management styles at the factories and get a better idea of what works and what doesn't work. This of course requires them to travel between the factories, which brings up Yuri's second problem: while
he won't be paying his children anything (their weekly allowance is more than adequate), he's worried about the total of all the travel costs, and would like it to be as small as possible. Each child is expected to inspect each of their assigned factories once a month, always ending back at the factory they started at, so to minimize cost he gures he need only assign the factories to minimize the total distance of these factory tours. The more he thinks about this, the more important saving money becomes. He's willing to use as few as only one of his children if that's the cheapest way to inspect all the factories. For example, if Yuri had four factories placed as in the gure on the left below, he could employ just
one child, who could visit each factory for a monthly distance of 40 (assume here that the unlisted distances between factories are all > 10). However, if his factories were located as shown on the right, he would need to employ two children to obtain the monthly minimal distance of 40 (note: he could
use two children to achieve the minimal distance in the rst gure as well).

Since the number of factories changes over time, Yuri would like a program to determine the minimum distance he can expect for any layout of factories.

Input

The input le begins with a line containing a single integer m indicating the number of test cases. Each
test case starts with an integer n indicating the number of factories, where 2  n  100. The next n􀀀1
lines contain the positive integer distances between the factories: line 1 contains n􀀀1 values specifying
the distances between factory 1 and factories 2; 3; 4; : : : ; n; line 2 contains n 􀀀 2 values specifying the
distances between factory 2 and factories 3; 4; : : : ; n; and so on. The maximum distance between any
two factories is 1000. All distances between any three cities will satisfy the triangle inequality.

Output
For each test case display the minimum factory tour distance. You should always assume that Yuri has
at least n=2 kids for each set of n factories.
Sample Input

2
4
10 20 10
10 20
10
4
15 20 10
10 20
15

Sample Output
Case 1: 40
Case 2: 40

解题:KM最小权匹配

#include <bits/stdc++.h>
using namespace std;
const int maxn = 110;
const int INF = 0x3f3f3f3f;
int W[maxn][maxn],Lx[maxn],Ly[maxn],slack[maxn];
int n,Link[maxn];
bool S[maxn],T[maxn];
bool match(int u){
S[u] = true;
for(int v = 0; v < n; ++v){
if(T[v]) continue;
int d = Lx[u] + Ly[v] - W[u][v];
if(!d){
T[v] = true;
if(Link[v] == -1 || match(Link[v])){
Link[v] = u;
return true;
}
}else if(slack[v] > d) slack[v] = d;
}
return false;
}
void update(){
int d = INF;
for(int v = 0; v < n; ++v)
if(!T[v] && slack[v] < d)
d = slack[v];
for(int u = 0; u < n; ++u){
if(S[u]) Lx[u] -= d;
if(T[u]) Ly[u] += d;
else slack[u] -= d;
}
}
int KM(){
for(int u = 0; u < n; ++u){
Lx[u] = -INF;
Ly[u] = 0;
Link[u] = -1;
for(int v = 0; v < n; ++v)
Lx[u] = max(Lx[u],W[u][v]);
}
for(int u = 0; u < n; ++u){
for(int v = 0; v < n; ++v)
slack[v] = INF;
while(true){
memset(S,false,sizeof S);
memset(T,false,sizeof T);
if(match(u)) break;
update();
}
}
int ret = 0;
for(int v = 0; v < n; ++v)
if(Link[v] > -1) ret += W[Link[v]][v];
return ret;
}
int main(){
int kase,cs = 1,tmp;
scanf("%d",&kase);
while(kase--){
for(int i = 0; i < maxn; ++i) W[i][i] = -INF;
scanf("%d",&n);
for(int i = 0; i < n-1; ++i){
for(int j = i + 1; j < n; ++j){
scanf("%d",&tmp);
W[i][j] = W[j][i] = -tmp;
}
}
printf("Case %d: %d\n",cs++,-KM());
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: