首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> C++ 入門

HDU 3605 Escape:強連通分量縮點 + 最大流判斷可行性

     編輯:C++ 入門

題目大意

N 個人,每人有 M 種技能(0/1 向量)。M 個星球,每星球有容量上限。每人只能去技能匹配的星球(人技能向量與星球需求向量按位與全為 1?實際為:人技能 1 的位置,星球必須也有 1?題目實為:人有一組技能,星球要求一組技能,人技能包含星球要求即可去)。問是否所有人都能安排到星球。

核心洞察:技能向量只有 2ᴹ 種,M≤10 ⇒ 最多 1024 種

N 達 10⁵,但技能組合極少。將相同技能的人合併為一個節點(縮點),容量為該技能出現次數。構建流網絡:

  • 源點 S → 技能節點,容量 = 該技能人數。
  • 技能節點 → 星球節點,若技能滿足星球要求,容量 = INF。
  • 星球節點 → 匯點 T,容量 = 星球容量上限。

最大流 = N 則可行。

流網絡構建細節

  • 技能狀態壓縮為整數 mask = Σ skill[i]<。
  • 統計 cnt[mask]。
  • 星球需求同樣壓縮為 need[planet]。
  • 滿足條件:(mask & need[planet]) == need[planet](人技能包含星球需求)。

代碼實現(ISAP 最大流)

#include <bits/stdc++.h>
using namespace std;

const int INF = 1e9;
const int MAXV = 2000; // 1024 + 10 + 2

struct Edge { int to, cap, rev; };
vector<Edge> G[MAXV];
int level[MAXV], iter[MAXV];

void add_edge(int from, int to, int cap) {
    G[from].push_back({to, cap, (int)G[to].size()});
    G[to].push_back({from, 0, (int)G[from].size()-1});
}

void bfs(int s) {
    fill(level, level+MAXV, -1);
    queue<int> q; level[s]=0; q.push(s);
    while(!q.empty()) {
        int v=q.front(); q.pop();
        for(auto &e:G[v]) if(e.cap>0 && level[e.to]<0) {
            level[e.to]=level[v]+1; q.push(e.to);
        }
    }
}

int dfs(int v, int t, int f) {
    if(v==t) return f;
    for(int &i=iter[v]; i0 && level[v]0) { e.cap-=d; G[e.to][e.rev].cap+=d; return d; }
        }
    }
    return 0;
}

int max_flow(int s, int t) {
    int flow=0, f;
    while(true) {
        bfs(s);
        if(level[t]<0) return flow;
        fill(iter, iter+MAXV, 0);
        while((f=dfs(s,t,INF))>0) flow+=f;
    }
}

int main() {
    int n, m;
    while(scanf("%d%d", &n, &m)==2) {
        for(int i=0;i cnt(1< cap(m);
        for(int j=0;j skill nodes
        for(int mask=0; mask<(1< planet
        for(int mask=0; mask<(1< T
        for(int p=0; p

關鍵優化:縮點

  • 原圖:N(10⁵) 人節點 + M 星球 ⇒ 邊數巨大,Dinic/ISAP 超時/超內存。
  • 縮點後:≤1024 技能節點 + 10 星球 ⇒ 節點 ~1034,邊 ~10240,極小。
  • ISAP/Dinic 瞬時跑完。

複雜度分析

  • 構圖:O(N·M + 2ᴹ·M) ≈ 10⁶ + 10⁴。
  • 最大流:O(V²E) ISAP,V≈10³, E≈10⁴ ⇒ 極快。
  • 空間:O(V+E) ≈ 10⁴。

總結

本題核心是「狀態壓縮 + 縮點 + 最大流」。大數據範圍下,發現狀態空間小(2ᴹ)是破題關鍵。將同狀態實體合併為帶容量節點,將分配問題建模為流網絡,是經典套路。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved