回寝室收衣服,被雨困住。顺手水一题
题目要求每一个点都在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;
}