P4542 ZJOI2011 營救皮卡丘

2022-08-19 14:27:11 字數 1454 閱讀 1249

營救皮卡丘

求用 \(k\) 條從 \(0\) 號節點出發的路徑覆蓋整個圖的最小距離和。

其中只有在 \(1\sim i-1\) 號節點全部被遍歷之後才能走到 \(i\) 號節點。

其實第二個限制條件不用太管它,因為只要找到了 \(k\) 條路徑,大家先後按某種順序走總能滿足要求。

不過這個條件也不是沒有用,它給 floyd 傳遞閉包限制了條件。

之後問題變為:

用不超過 \(k\) 條以 \(0\) 為起點的路徑覆蓋乙個 dag 所有結點的最小總長度。

這是挺模板的一道題了,與普通 dag 的最小路徑點覆蓋的區別是多了 \(k\) 這個限制條件。

方法同樣是建立超級源點 \(s\),然後建邊 \(\rm (s,0,k)\),以及 \(\rm (s,i,1)(0< i\leq n)\)。

然後照常建邊,跑最小費用最大流即可。

#include#include#include#includeusing namespace std;

const int n = 500;

const int m = 100000;

const int inf = 0x3f3f3f3f;

int n, m, k, deg[n], d[n][n];

int read()

struct ek ed[m];

queueq;

void add(int u, int v, int w, int c); head[u] = cnt;

ed[++ cnt] = (edge); head[v] = cnt;

}bool spfa()}}

if(d[t] == inf) return false;

return true;

}void update()

ans += incf[t] * d[t];

maxflow += incf[t];

}int work(int s, int t)

} t;

int main()

for(int i = 1; i <= m; i ++)

for(int k = 1; k <= n; k ++)

for(int i = 1; i <= n; i ++)

for(int j = 1; j <= n; j ++)

if(k < max(i, j))

d[i][j] = min(d[i][j], d[i][k] + d[k][j]);

int s = 0, t = n * 2 + 1;

t.add(s, 1, k, 0);

for(int i = 1; i <= n; i ++)

printf("%d\n", t.work(s, t));

return 0;

}

P4542 ZJOI2011 營救皮卡丘

傳送門 分析一下題目,發現每個點必須至少走過一次,並且對於乙個人的路徑,他摧毀的點編號一定是遞增的 並且在摧毀點 i 之前,他不能經過 i 1 到 n 的點,考慮設 dis i j i 因為最終每個點都會被摧毀,那麼乙個人的總路程就是 dis 0 p 1 sum dis p p i p i 表示這個...

bzoj2324 ZJOI2011 營救皮卡丘

description 皮卡丘被火箭隊用 的計謀搶走了!這三個壞傢伙還給小智留下了赤果果的挑釁!為了皮卡丘,也為了正義,小智和他的朋友們義不容辭的踏上了營救皮卡丘的道路。火箭隊一共有n個據點,據點之間存在m條雙向道路。據點分別從1到n標號。小智一行k人從真新鎮出發,營救被困在n號據點的皮卡丘。為了方...

ZJOI2011 營救皮卡丘

題面 神仙題。做最小路徑覆蓋。有乙個很像的地方,就是最小路徑覆蓋必須覆蓋到每個點,這道題也一樣。這道題有4個和最小路徑覆蓋不一樣的地方 可以重複訪問 這個可以用 floyed 傳遞閉包解決 每條路徑必須從原點出發 每個點必須被 到達 並不能乙個節點成乙個路徑 假設已經訪問了 1.x 那麼至少有乙個人...