当前位置:首页 >> 跨学科知识体系 >> 【SPOJ - TOURS 387】Travelling tours (最小费用最大流,拆点),xperia c s39h

【SPOJ - TOURS 387】Travelling tours (最小费用最大流,拆点),xperia c s39h

cpugpu芯片开发光刻机 跨学科知识体系 1
文件名:【SPOJ - TOURS 387】Travelling tours (最小费用最大流,拆点),xperia c s39h 【SPOJ - TOURS 387】Travelling tours (最小费用最大流,拆点)

题干:

In Hanoi, there are N beauty-spots (2 <= N <= 200), connected by M one-way streets. The length of each street does not exceed 10000. You are the director of a travel agency, and you want to create some tours around the city which satisfy the following conditions:

Each of the N beauty-spots belongs to exactly one tour.Each tour is a cycle which consists of at least 2 places and visits each place once (except for the place we start from which is visited twice).The total length of all the streets we use is minimal.Input

The first line of input contains the number of testcases t (t <= 15). The first line of each testcase contains the numbers N, M. The next M lines contain three integers U V W which mean that there is one street from U to V of length W.

Output

For each test case you shold output the minimal total length of all tours.

Example Input:26 91 2 52 3 53 1 103 4 124 1 84 6 115 4 75 6 96 5 45 81 2 42 1 71 3 103 2 103 4 104 5 105 3 105 4 3Output:4240Detailed explanation:Test 1:Tour #1: 1 - 2 - 3 - 1 --> Length = 20Tour #2: 6 - 5 - 4 - 6 --> Length = 22Test 2:Tour #1: 1 - 3 - 2 - 1 --> Length = 27Tour #2: 5 - 4 - 5 --> Length = 13

题目大意:

把一张带权有向图划分成一个或多个环,使环的总权值最小。

解题报告:

类似于二分图的最小路径覆盖,拆点。把每个点 u 拆成两个点 u1 和 u2, 然后每条边 u->v 改写成 u1---v2,就得到了一个二分图最佳匹配的模型。 由于“把一张带权有向图划分成一个或多个环”其实 等价于“每一个点都保留一个入度和一个出度” ,而匹配模型正好能满足这一点。于是建图跑模板就可以了、、

AC代码:

#include<cstdio>#include<iostream>#include<algorithm>#include<queue>#include<map>#include<vector>#include<set>#include<string>#include<cmath>#include<cstring>#define ll long longusing namespace std;const int MAXN = 70000;const int MAXM = 100005;const int INF = 0x3f3f3f3f;struct Edge {int to,next,cap,flow,cost;} edge[MAXM];int head[MAXN],tol;int pre[MAXN],dis[MAXN];bool vis[MAXN];int N;void init(int n) {N = n;tol = 0;memset(head, -1,sizeof(head));}void addedge(int u,int v,int cap,int cost) {edge[tol].to = v;edge[tol].cap = cap;edge[tol].cost = cost;edge[tol].flow = 0;edge[tol].next = head[u];head[u] = tol++;edge[tol].to = u;edge[tol].cap = 0;edge[tol].cost = -cost;edge[tol].flow = 0;edge[tol].next = head[v];head[v] = tol++;}bool spfa(int s,int t) {queue<int>q;for(int i = 0; i <= N; i++) {dis[i] = INF;vis[i] = false;pre[i] = -1;}dis[s] = 0;vis[s] = true;q.push(s);while(!q.empty()) {int u = q.front();q.pop();vis[u] = false;for(int i = head[u]; i !=-1; i = edge[i].next) {int v = edge[i].to;if(edge[i].cap > edge[i].flow && dis[v] > dis[u] + edge[i].cost ) {dis[v] = dis[u] + edge[i].cost;pre[v] = i;if(!vis[v]) {vis[v] = true;q.push(v);}}}}if(pre[t] ==-1)return false;else return true;}int minCostMaxflow(int s,int t,int &cost) {int flow = 0;cost = 0;while(spfa(s,t)) {int Min = INF;for(int i = pre[t]; i !=-1; i = pre[edge[i^1].to]) {if(Min > edge[i].cap-edge[i].flow)Min = edge[i].cap-edge[i].flow;}for(int i = pre[t]; i !=-1; i = pre[edge[i^1].to]) {edge[i].flow += Min;edge[i^1].flow-= Min;cost += edge[i].cost * Min;}flow += Min;}return flow;}int main(){int n,m;int t;scanf("%d",&t);while(t--) {scanf("%d%d",&n,&m);init(2*n+1);int st=0,ed=2*n+1;for(int i = 1,a,b,w; i<=m; i++) {scanf("%d%d%d",&a,&b,&w);addedge(a,b+n,1,w);}for(int i = 1; i<=n; i++) addedge(st,i,1,0);for(int i = n+1; i<=2*n; i++) addedge(i,ed,1,0);int cost;int ans = minCostMaxflow(st,ed,cost);printf("%d\n",cost);}return 0 ;}

 

协助本站SEO优化一下,谢谢!
关键词不能为空
同类推荐
«    2025年12月    »
1234567
891011121314
15161718192021
22232425262728
293031
控制面板
您好,欢迎到访网站!
  查看权限
网站分类
搜索
最新留言
文章归档
网站收藏
友情链接