hdu 3488

题意:给出一个有向图,边带权,求一些环,使得每个点属于且仅属于一个环,幷最小化环边的权值和。

思想和最小路径覆盖是一样的,将每个定点拆成两个点,假设u拆成u1,u2,那么所有边(v,u)对应新图中的(v1,u2),(u,v)对应(u1,v2)。

然后会发现一种合法方案和新图(是一个二分图)的一个完美匹配一一对应。

然后就可以用KM或网络流解决了。

(这种有向图路径拆边的思想很漂亮)

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <queue>
 4 #include <vector>
 5 #define oo 0x3f3f3f3f
 6 #define maxn 410
 7 using namespace std;
 8
 9 struct Edge {
10     int u, v, c, f;
11     Edge( int u, int v, int c, int f ):u(u),v(v),c(c),f(f){}
12 };
13 struct Mcmf {
14     int n, src, dst;
15     vector<Edge> edge;
16     vector<int> g[maxn];
17     int dis[maxn], ext[maxn], pth[maxn];
18
19     void init( int nn, int s, int d ) {
20         n = nn;
21         src = s;
22         dst = d;
23         for( int i=1; i<=n; i++ )
24             g[i].clear();
25         edge.clear();
26     }
27     void add_edge( int u, int v, int c, int f ) {
28         g[u].push_back( edge.size() );
29         edge.push_back( Edge(u,v,c,f) );
30         g[v].push_back( edge.size() );
31         edge.push_back( Edge(v,u,-c,0) );
32     }
33     bool spfa( int &flow, int &cost ) {
34         queue<int> qu;
35         memset( dis, 0x3f, sizeof(dis) );
36         qu.push( src );
37         dis[src] = 0;
38         ext[src] = true;
39         pth[src] = -1;
40         while( !qu.empty() ) {
41             int u=qu.front();
42             qu.pop();
43             ext[u] = false;
44             for( int t=0; t<g[u].size(); t++ ) {
45                 Edge &e = edge[g[u][t]];
46                 if( e.f && dis[e.v]>dis[e.u]+e.c ) {
47                     dis[e.v] = dis[e.u]+e.c;
48                     pth[e.v] = g[u][t];
49                     if( !ext[e.v] ) {
50                         ext[e.v] = true;
51                         qu.push( e.v );
52                     }
53                 }
54             }
55         }
56         if( dis[dst]==oo ) return false;
57         int flw = oo;
58         for( int eid=pth[dst]; eid!=-1; eid=pth[edge[eid].u] )
59             flw = min( flw, edge[eid].f );
60         for( int eid=pth[dst]; eid!=-1; eid=pth[edge[eid].u] ) {
61             edge[eid].f -= flw;
62             edge[eid^1].f += flw;
63         }
64         flow += flw;
65         cost += flw*dis[dst];
66         return true;
67     }
68     void mcmf( int &flow, int &cost ) {
69         flow = cost = 0;
70         while( spfa(flow,cost) );
71     }
72 };
73
74 int n, m;
75 Mcmf M;
76
77 int main() {
78     int T;
79     scanf( "%d", &T );
80     while(T--) {
81         scanf( "%d%d", &n, &m );
82         int tot = n+n+2;
83         M.init( tot, tot-1, tot );
84         for( int i=1,u,v,w; i<=m; i++ ) {
85             scanf( "%d%d%d", &u, &v, &w );
86             M.add_edge( u, v+n, w, 1 );
87         }
88         for( int u=1; u<=n; u++ ) {
89             M.add_edge( M.src, u, 0, 1 );
90             M.add_edge( u+n, M.dst, 0, 1 );
91         }
92         int flow, cost;
93         M.mcmf(flow,cost);
94         printf( "%d\n", cost );
95     }
96 }

时间: 2024-10-13 10:28:17

hdu 3488的相关文章

hdu1853/ hdu 3488 有向图,取k个圈覆盖所有点一次//费用流

哎╮(╯▽╰)╭,这是费用流基础题型,拆点,建二分图,跑最小费用最大流即可.若最大流为n,则说明是最大匹配为n,所有点都参与,每个点的入度和出度又是1,所以就是环. 弱菜还需努力! #include<cstdio> #include<iostream> #include<queue> #include<cstring> using namespace std; const int inf=0x3f3f3f3f; int nume=0;int e[50000]

Hdu 3488 Tour (KM 有向环覆盖)

题目链接: Hdu 3488 Tour 题目描述: 有n个节点,m条有权单向路,要求用一个或者多个环覆盖所有的节点.每个节点只能出现在一个环中,每个环中至少有两个节点.问最小边权花费为多少? 解题思路: 因为每个节点就出现一个,那么每个节点出度和入度都为1咯.我们可以对每个节点u拆点为u,u',分别放在集合X,Y.然后对两个集合进行完备匹配.完备匹配成功以后,每个节点就会有只有一个出度,一个入度的. 用KM求最小匹配的话,先初始化maps为-INF,然后把各边权值存为负,求出最大值取反即可. 1

Tour HDU - 3488

Tour HDU - 3488 可以用费用流做 1 #include <bits/stdc++.h> 2 using namespace std; 3 const int inf = 0x3f3f3f3f; 4 const int maxv = 410; 5 const int maxe = maxv * maxv; 6 7 struct Edge{ 8 int u, v, cap, flow, cost; 9 int nxt; 10 Edge(int u = 0, int v = 0, in

hdu 3488(KM算法||最小费用最大流)

Tour Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)Total Submission(s): 2925    Accepted Submission(s): 1407 Problem Description In the kingdom of Henryy, there are N (2 <= N <= 200) cities, with M (M <= 30000

HDU 3488 Tour【多个环的并】

大意:告诉你一些国家和一些单项路,每条路连接两个国家,告诉你之间的距离,现在要使每个国家都在一个环中 求最小距离 分析:这是做过的第二个多个环的并的问题 每个点的入读和出度都为1 把n个点拆点 由于二分图最优匹配的性质可知每个点都会出现在匹配中 相当于每个点出现一次 左边为出度点  有边为入读点 值得注意的是两个国家可能会有多条路 要选取最短的 ----想起东北赛死在这上边了   ----全都是泪啊 代码: 1 #include <iostream> 2 #include <cstdio

HDU 3488 Tour

有向环最小权值覆盖问题 http://blog.csdn.net/u013480600/article/details/39159407 #include<cstdio> #include<cstring> #include<cmath> #include<vector> #include<queue> #include<algorithm> using namespace std; //设置节点数量 const int maxn=4

Q - Tour - hdu 3488(最小匹配值)

题意:一个王国有N个城市,M条路,都是有向的,现在可以去旅游,不过走的路只能是环(至少也需要有两个城市),他们保证这些城市之间的路径都是有环构成的,现在至少需要走多少路. 分析:因为是有向图所以,而且走的是环所以每个城市都会进入一次并且出去一次,构成二分图,并且是完备匹配(完备匹配后肯定都是环了),现在只需要求出来这些匹配的最小值就行,可以把路径的值变为负数,然后求最大匹配值,最后的结果在变成相反数即可,注意路径可能有多条,输入的时候注意取最小的那个 **********************

HDU 3435 A new Graph Game(最小费用最大流)&amp;amp;HDU 3488

A new Graph Game Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1849    Accepted Submission(s): 802 Problem Description An undirected graph is a graph in which the nodes are connected by undir

HDU 3435 A new Graph Game(最小费用最大流)&amp;HDU 3488

A new Graph Game Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1849    Accepted Submission(s): 802 Problem Description An undirected graph is a graph in which the nodes are connected by undir