UVA12092 Paint the Roads 费用流

回寝室收衣服,被雨困住。顺手水一题

题目要求每一个点都在k个环中,且不共线(有向图)的最小费用。费用即边权。费用流拆点即可

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

 


#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>

using namespace std;

#define MAXN 1000
#define MAXM 20000
#define INF 0xFFFFFF
struct edge
{
	int to,c,w,next;
};

edge e[MAXM];
bool in[MAXN];
int head[MAXN],dis[MAXN],pre[MAXN],en,maxflow,mincost;
int vn,st,ed;
int n,m,k;

void add(int a,int b,int c,int d)
{
	e[en].to=b;
	e[en].c=c;
	e[en].w=d;
	e[en].next=head[a];
	head[a]=en++;
	e[en].to=a;
	e[en].c=0;
	e[en].w=-d;
	e[en].next=head[b];
	head[b]=en++;
}

bool spfa(int s)
{
	queue<int> q;
	for(int i=0;i<=vn;i++)
	{
		dis[i]=INF;
		in[i]=false;
		pre[i]=-1;
	}
	dis[s]=0;
	in[s]=true;
	q.push(s);
	while(!q.empty())
	{
		int tag=q.front();
		in[tag]=false;
		q.pop();
		for(int i=head[tag];i!=-1;i=e[i].next)
		{
			int j=e[i].to;
			if(e[i].w+dis[tag]<dis[j] && e[i].c)
			{
				dis[j]=e[i].w+dis[tag];
				pre[j]=i;
				if(!in[j])
				{
					q.push(j);
					in[j]=true;
				}
			}
		}
	}
	if(dis[ed]==INF)
		return false;
	return true;
}

void update()
{
	int flow=INF;
    for (int i=pre[ed];i!=-1;i=pre[e[i^1].to])
		if(e[i].c<flow) flow=e[i].c;
    for (int i=pre[ed];i!=-1;i=pre[e[i^1].to])
    {
		e[i].c-=flow,e[i^1].c+=flow;
	}
    maxflow+=flow;
    mincost+=flow*dis[ed];
}

void mincostmaxflow()
{
	maxflow=0,mincost=0;
	while(spfa(st)) update();
}


int main()
{
    int cs;
    scanf("%d",&cs);
    for(int i=1;i<=cs;i++)
    {
        scanf("%d%d%d",&n,&m,&k);
        memset(head,-1,sizeof(head));
        en=0;vn=n*2+2;st=0,ed=n*2+1;
        for(int i=1;i<=n;i++)
        {
            add(st,i,k,0);
            add(i+n,ed,k,0);
        }
        for(int i=0;i<m;i++)
        {
            int u,v,d;
            scanf("%d%d%d",&u,&v,&d);
            u++,v++;
            add(u,v+n,1,d);
        }
        mincostmaxflow();
        if(maxflow!=n*k)
            printf("-1\n");
        else
            printf("%d\n",mincost);
    }
    return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值