The first line of each test case contains two integers N (N ≤ 100) and M, indicating the number of cities and the number of roads. The M lines followed, each of them contains three numbers A, B, and C, indicating that there is a road from city A to city B, whose length is C. (1 ≤ A,B ≤ N, A ≠ B, 1 ≤ C ≤ 1000).
OutputOutput one number for each test case, indicating the minimum length of all the tours. If there are no such tours, output -1.
Sample Input
6 9 1 2 5 2 3 5 3 1 10 3 4 12 4 1 8 4 6 11 5 4 7 5 6 9 6 5 4 6 5 1 2 1 2 3 1 3 4 1 4 5 1 5 6 1Sample Output
42
-1
Hint
In the first sample, there are two cycles, (1->2->3->1) and (6->5->4->6) whose length is 20 + 22 = 42.
题意:给你N个点,M条有向边,让你连接n个环(点的个数>=2)使得花费最小,如果无法实现输出-1
思路:k个点组成一个环需要k条边,所以n个点无论组成多少个环都需要n条边,所以可以用最大流来判断是否有解,加上最小费用来求答案。源点为0,左部为1~n,右部为n+1~n*2,汇点会n*2+1。源点与左部每个点连接,右部每个点与汇点连接,对于每条有向边x与n+y连接。
这题有个坑点就是有重边(被坑n发。。。)
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
using namespace std;
#define N 210
#define M 30410
#define inf 1000000007
typedef struct
{
int u,v,w1,w2,next;
}Node;
Node e[M*2];
int head[N*2],vis[N*2],d[N*2],fa[N*2];
int n,m,tot,res;
int s[N][N];
void add(int x,int y,int z1,int z2)
{
e[tot].u=x;
e[tot].v=y;
e[tot].w1=z1;
e[tot].w2=z2;
e[tot].next=head[x];
head[x]=tot++;
}
int Spfa(int s,int t,int du)
{
memset(vis,0,sizeof(vis));
int i,j,u,x,y;
for(i=0;i<=du;i++)
{
fa[i]=-1;
d[i]=inf;
}
queue<int> q;
d[s]=0;
vis[s]=1;
q.push(s);
while(!q.empty())
{
u=q.front();
q.pop();
vis[u]=0;
for(i=head[u];i!=-1;i=e[i].next)
{
x=e[i].v;
if(e[i].w1>0&&d[x]>d[u]+e[i].w2){
d[x]=d[u]+e[i].w2;
fa[x]=i;
if(vis[x]==0)
{
vis[x]=1;
q.push(x);
}
}
}
}
if(fa[t]==-1)
return 0;
return 1;
}
int MCMF(int s,int t,int du)
{
int ans=0,i,x,y=0;
while(Spfa(s,t,du))
{
x=inf+1;
for(i=fa[t];i!=-1;i=fa[e[i].u])
x=min(x,e[i].w1);
y=y+x;
for(i=fa[t];i!=-1;i=fa[e[i].u])
{
e[i].w1-=x;
e[i^1].w1+=x;
}
ans+=d[t]*x;
}
res=y;
return ans;
}
int main()
{
int i,j,k,t,x,y,z,ans;
while(scanf("%d%d",&n,&m)!=EOF)
{
tot=0;
memset(head,-1,sizeof(head));
for(i=0;i<=n;i++)
for(j=0;j<=n;j++)
s[i][j]=inf;
for(i=0;i<m;i++)
{
scanf("%d%d%d",&x,&y,&z);
s[x][y]=min(s[x][y],z);
}
for(i=0;i<=n;i++)
for(j=0;j<=n;j++)
if(s[i][j]!=inf)
{
add(i,n+j,1,s[i][j]);
add(n+j,i,0,-s[i][j]);
}
for(i=1;i<=n;i++)
{
add(0,i,1,0);
add(i,0,0,0);
add(n+i,n*2+1,1,0);
add(n*2+1,n+i,0,0);
}
ans=MCMF(0,n*2+1,n*2+2);
if(res!=n)
printf("-1\n");
else
printf("%d\n",ans);
}
return 0;
}