您的位置:首页 > 大数据 > 人工智能

(intermediate) 最小费用流 UVA 12092 - Paint the Roads

2014-03-07 15:30 513 查看
H
Paint the Roads
Input: Standard Input
Output: Standard Output
 


In a country there are n cities connected by m one way roads. You can paint any of these roads. To paint a road it costs d unit of money
where d is the length of that road. Your task is to paint some of the roads so that the painted roads can be partitioned into some disjoint cycles such that every vertex appears in exactly k of these disjoint cycles. But you have to minimize the costs of painting
these roads.

 
Input
First line of the input contains T the number of test case. Then following lines contains T Test cases.

 

Each case starts with a line containing 3 integers n (1 ≤ n ≤ 40), m (1 ≤ m ≤ 2000) and k (1 ≤ k and 1≤k*n≤100). Next m lines contain description of m roads. Each line contains three integers f, t (0 ≤ f, t <n and f ≠ t) and d (0 ≤ d < 100). That means there
is a road of d length from city f to city t. You can assume that there will be at most one road in one direction between two cities.

 

Output

For each test case output contains 1 integer denoting the minimum unit of money needed to paint roads. In the case it is impossible to paint the roads maintaining the constraints output -1.

 

Sample Input                             Output for Sample Input

4

 

4 8 1

0 1 1

1 0 2

2 3 1

3 2 2

0 2 5

2 0 6

1 3 5

3 1 6

 

4 8 1

0 1 1

1 0 10

2 3 10

3 2 1

0 2 10

2 0 1

1 3 1

3 1 10

 

4 8 2

0 1 1

1 0 2

2 3 1

3 2 2

0 2 5

2 0 6

1 3 5

3 1 6

 

3 4 1

0 1 5

1 0 6

0 2 7

2 0 8

 

6

4

28

-1

 

Problem setter: Abdullah al Mahmud, Special Thanks: Derek Kisman

题意:有n个城市,m条单向的道路,每两个城市之间最短只有一条道路直接连接。你需要为某些路涂上颜色,问这些边能否使得每一个城市刚好在k个没有公共边的环中。如果可以,由于每条路涂颜色的价格不同,请输出最少需要多少钱。



思路:一个点在k个不相交的环中说明每一个城市的入度等于出度等于k,根据这个建图。我们把每个城市拆成两个点,一个表示入度,一个表示出度,然后对于两个城市直接相连的话,从一个城市的入度连向另一个城市的出度,容量为1,费用就是这条路的费用,然后加一个源点,一个汇点,源点连向所有的入度,容量为k,费用为0,所有的出度连向汇点,容量为k,费用为0,然后跑一个最小费用流,如果流量满了,说明实现,就输出费用,否则的话就无解了。至于为什么每个点入度和出度都是k就一定是在k个环里面。。。我也不知道



代码:

#include<iostream>
#include<algorithm>
#include<vector>
#include<string.h>
#include<queue>
#include<cstring>
#include<cstdio>
using namespace std;
const int maxn=40*2+10;
const int inf=1e8;
struct Edge
{
int u,v,w;
int flow,cap;
Edge(int u,int v,int cap,int flow,int cost)
:u(u),v(v),cap(cap),flow(flow),w(cost) {}
};

vector<Edge> edges;
vector<int> G[maxn];

void add(int u,int v,int cap,int cost)
{
edges.push_back(Edge(u,v,cap,0,cost));
edges.push_back(Edge(v,u,0,0,-cost));
int m=edges.size();
G[u].push_back(m-2);
G[v].push_back(m-1);
}

struct MCMF
{
int a[maxn],d[maxn],p[maxn];
bool inq[maxn];
int n,s,t;
void init(int n)
{
this->n=n;
}
bool spfa(int s,int t,int&flow,int&cost)
{
this->s=s,this->t=t;
for(int i=0;i<n;++i) a[i]=d[i]=inf;
memset(inq,0,sizeof(inq));
queue<int> q;
q.push(s);
inq[s]=true;
d[s]=0;
while(q.size())
{
int x=q.front(); q.pop();
inq[x]=false;
for(int i=0;i<G[x].size();++i)
{
Edge&e=edges[G[x][i]];
if(e.cap<=e.flow) continue;
int y=e.v,w=e.w;
if(d[y]<=d[x]+w) continue;
d[y]=d[x]+w;
p[y]=G[x][i];
a[y]=min(a[x],e.cap-e.flow);
if(!inq[y]) q.push(y);
inq[y]=true;
}
}
if(d[t]==inf) return false;
flow+=a[t];
cost+=a[t]*d[t];
int x=t;
while(x!=s)
{
edges[p[x]].flow+=a[t];
edges[p[x]^1].flow-=a[t];
x=edges[p[x]].u;
}
return true;
}

int maxflow(int s,int t,int maxf)
{
int flow=0,cost=0;
while(spfa(s,t,flow,cost));
if(flow<maxf) return -1;
return cost;
}
}solver;

int n,m,k;
void input()
{
edges.clear();
for(int i=0;i<maxn;++i) G[i].clear();
scanf("%d%d%d",&n,&m,&k);
while(m--)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add(2*u,2*v+1,1,w);
}
for(int i=0;i<2*n;i+=2) add(2*n,i,k,0);
for(int i=1;i<2*n;i+=2) add(i,2*n+1,k,0);

}

void solve()
{
solver.init(2*n+2);
int ret=solver.maxflow(2*n,2*n+1,k*n);
printf("%d\n",ret);
}

int main()
{
int T;cin>>T;
while(T--)
{
input();
solve();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息