题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3488
题意:给你一个N个顶点M条边的带权有向图,要你把该图分成1个或多个不相交的有向环.且所有定点都只被一个有向环覆盖.问你该有向环所有权值的总和最小是多少?(哈密顿图)
题目分类:最小费用最大流
题目代码:
#include<bits/stdc++.h> using namespace std; #define INF 1e9
using namespace std;
const int maxn=+; struct Edge
{
int from,to,cap,flow,cost;
Edge(){}
Edge(int f,int t,int c,int fl,int co):from(f),to(t),cap(c),flow(fl),cost(co){}
}; struct MCMF
{
int n,m,s,t;
vector<Edge> edges;
vector<int> G[maxn];
bool inq[maxn];
int d[maxn];
int p[maxn];
int a[maxn]; void init(int n,int s,int t)
{
this->n=n, this->s=s, this->t=t;
edges.clear();
for(int i=;i<n;++i) G[i].clear();
} void AddEdge(int from,int to,int cap,int cost)
{
edges.push_back(Edge(from,to,cap,,cost));
edges.push_back(Edge(to,from,,,-cost));
m=edges.size();
G[from].push_back(m-);
G[to].push_back(m-);
} bool BellmanFord(int &flow,int &cost)
{
queue<int> Q;
for(int i=;i<n;++i) d[i]=INF;
memset(inq,,sizeof(inq));
Q.push(s),inq[s]=true,d[s]=,a[s]=INF,p[s]=; while(!Q.empty())
{
int u=Q.front(); Q.pop();
inq[u]=false;
for(int i=;i<G[u].size();++i)
{
Edge &e=edges[G[u][i]];
if(e.cap>e.flow && d[e.to]>d[u]+e.cost)
{
d[e.to]=d[u]+e.cost;
a[e.to]=min(a[u],e.cap-e.flow);
p[e.to]=G[u][i];
if(!inq[e.to]){inq[e.to]=true; Q.push(e.to);}
}
}
}
if(d[t]==INF) return false;
flow += a[t];
cost += a[t]*d[t];
int u=t;
while(u!=s)
{
edges[p[u]].flow +=a[t];
edges[p[u]^].flow -=a[t];
u=edges[p[u]].from;
}
return true;
} int solve(int num)
{
int flow=,cost=;
while(BellmanFord(flow,cost));
return flow==num?cost:-;
}
}MM; int main()
{
int T;scanf("%d",&T);
while(T--)
{
int n,m;
scanf("%d%d",&n,&m);
int src=,dst=*n+;
MM.init(*n+,src,dst);
for(int i=;i<=n;++i)
{
MM.AddEdge(src,i,,);
MM.AddEdge(i+n,dst,,);
}
while(m--)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
MM.AddEdge(u,v+n,,w);
}
printf("%d\n",MM.solve(n));
}
return ;
}