zoukankan      html  css  js  c++  java
  • POJ 2594 Treasure Exploration (可相交最小路径覆盖)

    题意

    给你张无环有向图,问至少多少条路径能够覆盖该图的所有顶点——并且,这些路径可以有交叉。

    思路

    不是裸的最小路径覆盖,正常的最小路径覆盖中两个人走的路径不能有重复的点,而本题可以重复。 当然我们仍可将问题转化为最小路径覆盖。如果一个人需要经过另一个人走过的点的时候,让他直接从该点上空飞过去,越过该点,直接走下一个点。如果我们赋予每个人这种能力,那么求得的无重复点的最小路径覆盖结果,就是题目要求的结果,因为需要重复的地方只要飞过去,就可以不重复了。赋予这个能力的方法就是预处理用Floyd求传递闭包把所有点能间接到达的点全都改为直接到达。然后正常求最小路径覆盖即可。

    代码

      [cpp] #include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <algorithm> #include <string> #include <cstring> #define MID(x,y) ((x+y)/2) #define MEM(a,b) memset(a,b,sizeof(a)) #define REP(i, begin, m) for (int i = begin; i < begin+m; i ++) using namespace std; const int MAXV = 1005; //|V1|+|V2| struct MaximumMatchingOfBipartiteGraph{ int vn; vector <int> adj[MAXV]; void init(int n){ //二分图两点集点的个数 vn = n; for (int i = 0; i <= vn; i ++) adj[i].clear(); } void add_uedge(int u, int v){ adj[u].push_back(v); adj[v].push_back(u); } bool vis[MAXV]; int mat[MAXV]; //记录已匹配点的对应点 bool cross_path(int u){ for (int i = 0; i < (int)adj[u].size(); i ++){ int v = adj[u][i]; if (!vis[v]){ vis[v] = true; if (mat[v] == 0 || cross_path(mat[v])){ mat[v] = u; mat[u] = v; return true; } } } return false; } int hungary(){ MEM(mat, 0); int match_num = 0; for (int i = 1; i <= vn; i ++){ MEM(vis, 0); if (!mat[i] && cross_path(i)){ match_num ++; } } return match_num; } void print_edge(){ for (int i = 1; i <= vn; i ++){ for (int j = 0; j < (int)adj[i].size(); j ++){ printf("u = %d v = %d ", i, adj[i][j]); } } } }match; bool reach[MAXV>>1][MAXV>>1]; void floyd(int n){ REP(k, 1, n) REP(i, 1, n) REP(j, 1, n){ if (reach[i][j]) continue; reach[i][j] = reach[i][k] && reach[k][j]; } } int main(){ //freopen("test.in", "r", stdin); //freopen("test.out", "w", stdout); int n, m; while(scanf("%d %d", &n, &m), n+m){ if (0 == m){ printf("%d ", n); continue; } MEM(reach, false); REP(i, 0, m){ int u, v; scanf("%d %d", &u, &v); reach[u][v] = true; } floyd(n); match.init(n); REP(i, 1, n) REP(j, 1, n){ if (reach[i][j]) match.add_uedge(i, j+n); } printf("%d ", n-match.hungary()); } return 0; } [/cpp]
  • 相关阅读:
    C++随笔
    STM32调试总结
    摄像头CMOS和CCD的比较
    modelsim 中 WAVE窗口中能不能只显示变量名,而不显示路径
    modelsim仿真xilinx mig ip core相关问题
    modelsim仿真vivado自动化脚本
    modelsim无法识别include文件的解决方法
    UVM的类库
    uvm
    uvm
  • 原文地址:https://www.cnblogs.com/AbandonZHANG/p/4114080.html
Copyright © 2011-2022 走看看