POJ 3216 Repairing Company(最小路徑覆蓋)
阿新 • • 發佈:2018-04-20
false 時間 cpp algorithm true 持續時間 set rgb AR
POJ 3216 Repairing Company
id=3216">題目鏈接
題意:有m項任務,每項任務的起始時間,持續時間,和它所在的block已知,且往返每對相鄰block之間的時間也知道,問最少須要多少個工人才幹完畢任務,即x最少是多少
思路:先floyd求出每兩個block之間的最小距離,然後就是最小路徑覆蓋問題,一個任務之後能趕到還有一個任務就建邊
代碼:
#include <cstdio> #include <cstring> #include <algorithm> #include <vector> using namespace std; const int N = 25; const int M = 205; const int INF = 0x3f3f3f3f; int n, m, q[N][N]; vector<int> g[M]; int in[M], s[M], d[M]; bool judge(int i, int j) { return s[i] + d[i] + q[in[i]][in[j]] <= s[j]; } int left[M], vis[M]; bool dfs(int u) { for (int i = 0; i < g[u].size(); i++) { int v = g[u][i]; if (vis[v]) continue; vis[v] = 1; if (left[v] == -1 || dfs(left[v])) { left[v] = u; return true; } } return false; } int hungary() { int ans = 0; memset(left, -1, sizeof(left)); for (int i = 0; i < m; i++) { memset(vis, 0, sizeof(vis)); if (dfs(i)) ans++; } return ans; } int main() { while (~scanf("%d%d", &n, &m) && n) { for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++) { scanf("%d", &q[i][j]); if (q[i][j] == -1) q[i][j] = INF; } for (int k = 1; k <= n; k++) { for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) { q[i][j] = min(q[i][j], q[i][k] + q[k][j]); } } } for (int i = 0; i < m; i++) { g[i].clear(); scanf("%d%d%d", &in[i], &s[i], &d[i]); for (int j = 0; j < i; j++) { if (judge(i, j)) g[i].push_back(j); if (judge(j, i)) g[j].push_back(i); } } printf("%d\n", m - hungary()); } return 0; }
POJ 3216 Repairing Company(最小路徑覆蓋)