最小路径覆盖合集
来源:互联网 发布:家庭网络拓扑 编辑:程序博客网 时间:2024/06/12 21:30
首先谈谈对最小路径覆盖核心函数的理解:每次从u出发寻找扩增点,若v已被其他点h扩增,则递归令h重新扩增另一个点,并把v的父节点指向h
int getNext(int u){ for (int i = head[u], v; i!= -1; i=next[i]) { if ( !vis[v=to[i]]) { vis[v] = 1; if (fa[v] == -1 || getNext(fa[v])) { fa[v] = u; return 1; } } } return 0;}
hdu 4606 Occupy Cities
图论(线段交叉),最小路径覆盖。。。。
貌似hdu的编译器有bug
#include <cstdio> #include <cstring> #include <iostream> #include <cmath> using namespace std; #define MAXN 310#define MAXM 100000int n, m, p;struct node{ int x, y;}data[MAXN];int seq[MAXN];double dis[MAXN][MAXN];int head[MAXN], to[MAXM], next[MAXM], szEdge;int vis[MAXN], fa[MAXN];void add(int u, int v){ to[szEdge] = v; next[szEdge] = head[u]; head[u] = szEdge++;}int getNext(int u){ for (int i = head[u], v; i!= -1; i=next[i]) { if ( !vis[v=to[i]]) { vis[v] = 1; if (fa[v] == -1 || getNext(fa[v])) { fa[v] = u; return 1; } } } return 0;}inline double getDis(int i, int j){ return sqrt( (double)(data[i].x-data[j].x)*(data[i].x-data[j].x) + (double)(data[i].y-data[j].y)*(data[i].y-data[j].y));}inline int getCross(node &n0, node &n1, node &n2){ return (n1.x-n0.x)*(n2.y-n0.y) - (n1.y-n0.y)*(n2.x-n0.x);}int isCross(node a1, node a2, node b1, node b2){ int d1 = getCross(a1,a2,b1), d2 = getCross(a1,a2,b2), d3 = getCross(b1,b2,a1), d4 = getCross(b1,b2,a2); if(((d1>0&&d2<0)||(d1<0&&d2>0))&&((d3>0&&d4<0)||(d3<0&&d4>0))) return 1; return 0;}int main(){#ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin);#endif // ONLINE_JUDGE int t, i; scanf("%d", &t); while (t--) { scanf("%d%d%d", &n, &m, &p); int cnt = n + 2*m; for ( i = 1; i<= n; ++i) scanf("%d%d", &data[i].x, &data[i].y); for (i = n+1; i<= cnt; ++i) scanf("%d%d", &data[i].x, &data[i].y); for (i = 1; i<= n; ++i) scanf("%d", &seq[i]); /// 初始化距离 for (i = 1; i<= cnt; ++i) { for (int j = i; j<= cnt; ++j) { if (i == j) dis[i][j] = 0.0; else { dis[j][i] = getDis(i,j); dis[i][j] = dis[j][i]; } } } /// 判断交叉 for (i = 1; i<= cnt ; ++i) { for (int j = i+1; j<= cnt; ++j) { if (dis[i][j] < 0.0) continue; for (int k = n+1; k <= cnt; k+=2) { if (isCross(data[i],data[j],data[k],data[k+1])) { dis[i][j] = dis[j][i] = -1; break; } } } } /// floyd for (i = 1; i<= cnt; ++i) for (int j = 1; j<= cnt; ++j) if (dis[j][i] != -1 ) for (int k = 1; k<= cnt; ++k) if (dis[i][k] != -1) { if (dis[j][k] == -1) dis[j][k] = dis[k][j] = dis[j][i] + dis[i][k]; else if (dis[j][k] > dis[j][i] + dis[i][k]) dis[j][k] = dis[k][j] = dis[j][i] + dis[i][k]; } double l = 0.0, r = 40000.0 , mid; const double inf = 1e-6; while (r-l > inf) { mid = (l+r)/2.0; memset(head, -1, sizeof head); memset(fa, -1, sizeof fa); szEdge = 0; for (i = 1; i<= n; ++i) for (int j = i+1; j<= n; ++j) if (dis[seq[i]][seq[j]] != -1 && dis[seq[i]][seq[j]] <= mid) add(seq[i], seq[j]); int tp = 0; /// 最小路径覆盖 for (i = 1; i<= n; ++i) { memset(vis, 0, sizeof vis); if (getNext(i)) ++tp; } if (n-tp <= p) r = mid; else l = mid; } printf("%.2lf\n", (l+r)/2.0); } return 0;}
hdu 4619 Warm up 2
匈牙利算法,但核心与最小路径覆盖一致,都是逐渐扩增
#include <stdio.h>#include <vector>#include <string.h>#include <math.h>using namespace std;#define MAXN 1005int fa[MAXN], vis[MAXN];struct _node{ int x, y;} dm[MAXN], dn[MAXN];vector<int> nxt[MAXN];int test ( int i, int j ){ _node a = dn[i], b = dm[j]; if ( a.x == b.x && a.y == b.y ) { return 1; } if ( a.x + 1 == b.x && a.y == b.y ) { return 1; } if ( a.x == b.x && a.y == b.y + 1 ) { return 1; } if ( a.x + 1 == b.x && a.y == b.y + 1 ) { return 1; } return 0;}int fnd ( int u ){ for ( unsigned int i = 0; i < nxt[u].size(); ++i ) { int v = nxt[u][i]; if ( vis[v] ) { continue; } vis[v] = 1; if ( fa[v] == -1 || fnd ( fa[v] ) ) { fa[v] = u; return 1; } } return 0;}int main(){#ifdef __GNUC__ freopen ( "in.txt", "r", stdin ); //freopen ( "out.txt", "w", stdout );#endif // __GNUC__ int n, m; while ( scanf ( "%d%d", &n , &m ) == 2 && ( m + n ) ) { for ( int i = 0; i < n; ++i ) { scanf ( "%d%d", &dn[i].x, &dn[i].y ); nxt[i].clear(); } for ( int i = 0; i < m; ++i ) { scanf ( "%d%d", &dm[i].x, &dm[i].y ); } for ( int i = 0; i < n; ++i ) { for ( int j = 0; j < m; ++j ) { if ( test ( i, j ) ) { nxt[i].push_back ( j ); } } } memset ( fa, -1, sizeof fa ); int cnt = 0; for ( int i = 0; i < n; ++i ) { memset ( vis, 0, sizeof vis ); if ( fnd ( i ) ) { cnt++; } } printf ( "%d\n", n + m - cnt ); } return 0;}
hdu 1150 Machine Schedule
最小点覆盖#include <stdio.h>#include <vector>#include <string.h>#include <math.h>using namespace std;#define MAXN 1005int fa[MAXN], vis[MAXN];struct _node{ int x, y;} dm[MAXN], dn[MAXN];vector<int> nxt[MAXN];int fnd ( int u ){ for ( unsigned int i = 0; i < nxt[u].size(); ++i ) { int v = nxt[u][i]; if ( vis[v] ) { continue; } vis[v] = 1; if ( fa[v] == -1 || fnd ( fa[v] ) ) { fa[v] = u; return 1; } } return 0;}int main(){#ifdef __GNUC__ freopen ( "in.txt", "r", stdin ); //freopen ( "out.txt", "w", stdout );#endif // __GNUC__ int n, m, k; while ( scanf ( "%d", &n ) && n ) { scanf ( "%d%d", &m, &k ); for ( int i = 0; i < n; ++i ) { nxt[i].clear(); } for ( int i = 0, j; i < k; ++i ) { int u, v; scanf ( "%d%d%d", &j, &u, &v ); if ( u && v) nxt[u].push_back ( v ); } memset ( fa, -1, sizeof fa ); int cnt = 0; for ( int i = 1; i < n; ++i ) { memset ( vis, 0, sizeof vis ); if ( fnd ( i ) ) { cnt++; } } printf ( "%d\n", cnt ); } return 0;}
- 最小路径覆盖合集
- 最小路径覆盖,最小点覆盖,最大独立点集
- 最小路径覆盖,最小点覆盖,最大独立点集
- 【最小路径覆盖】最小路径覆盖
- 【最小边覆盖 & 最小路径覆盖 & 最小顶点覆盖 & 最大独立集 & 最大团】
- 最大独立集 最小点覆盖 最小边覆盖 最小路径覆盖 最大团
- 【转载】【最小边覆盖 & 最小路径覆盖 & 最小顶点覆盖 & 最大独立集 & 最大团】
- 最小路径覆盖,最小点覆盖,最大独立点集,最小边覆盖
- 【最小边覆盖 & 最小路径覆盖 & 最小顶点覆盖 & 最大独立集 & 最大团】
- 最小点覆盖,最小边覆盖,最大匹配,最小路径覆盖,最大独立集总结。
- 最小路径覆盖
- 最小路径覆盖
- pku2594 最小路径覆盖
- 最小路径覆盖
- 最小路径覆盖
- poj1422最小路径覆盖
- 最小路径覆盖
- 最小路径覆盖:Divisibility
- Git详解之五:分布式Git
- 事务、存储过程和触发器和函数
- maven依赖本地非repository中的jar包
- Xfire生成WebService客户端时 jaxb-xjc 报错 Error generating JAXB model
- 书签
- 最小路径覆盖合集
- [转]50个c/c++源代码网站
- tar.xz如何解压
- GnuWin32——Windows下的GNU工具集
- 关于11.2.0.3.0的几个Bug事项
- 由5/2想到的
- 一种基于 JEP 和可配置公式实现用户自定义字段的解决方案
- 二分图带权最大独立集 网络流解决 hdu 1569
- 使用try、catch、finally语句块需要注意