營救皮卡丘
求用 \(k\) 條從 \(0\) 號節點出發的路徑覆蓋整個圖的最小距離和。其實第二個限制條件不用太管它,因為只要找到了 \(k\) 條路徑,大家先後按某種順序走總能滿足要求。其中只有在 \(1\sim i-1\) 號節點全部被遍歷之後才能走到 \(i\) 號節點。
不過這個條件也不是沒有用,它給 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 那麼至少有乙個人...