題目背景
。飛紛火戰來年近國 D 和國 C
。飛亂子鴿來年近國 D 和國 C
題面描述
最近,C 國成功地滲透進入了 D 國的一個城市。這個城市能夠抽象成一張有 n 個節點,節點之間有 m 條雙向道路鏈接的無向圖,每條道路的⻓度都爲 1 。
通過偵查,C 國情報部部⻓ GGB 驚訝地發現,這座看起來不起眼的城市居然是 D 國的軍事中心。所以 GGB 決定在這個城市內設立情報機構。情報專家 TAC 在偵查後,安排了 q 種設立情報機構的方案。這些方案中,第 i 種方案將計劃創建 ki 個情報機構,第 j 個情報機構能夠安排人員到距離其不超過 di,j 的節點上收集情報。html
從文件 center.in 中讀入數據。
輸入第一行包含三個正整數 n, m, q ,分別表示城市的節點個數、道路條數和方案個數。
接下去 m 行每行兩個正整數 u, v ,表示存在一條鏈接城市 u 和城市 v 的雙向道路。
接下去 q 行,每行表示一個方案。第一個正整數 k 表示該種方案將計劃創建 k 個情報機構,以後是 2k 個正整數,其中第 2i − 1 個數表示方案中第 i 個情報機構所在的節點編號,第 2i 個數表示第 i 個情報點所能派出情報人員的最遠距離。c++
輸出到文件 center.out 中。
輸出包含 q 行,每行包含一個整數,表示相應詢問的答案。web
5 8 3
1 2
1 3
1 4
1 5
2 4
2 5
3 5
4 5
1 2 1
1 1 1
2 2 2 3 1數組
4
5
5app
題目更正:di,j值域在int範圍內;q小於等於100000svg
這題額,只有一個評價——語言歧視,不要臉。
首先,咱們一個直觀的想法——
f[i,j,k]表示第i個點,走了j步,可否到達k。
然而這樣子空間不保證。
嘗試把k當作一個狀態。
那麼就是:
f[i,j]表示第i個點,走了j步,能到達點的狀況。
pascal就要多加維k,把1000壓成32個longint存儲2進制。
C++好像有一個叫作bitset的好傢伙能夠用。
而後咱們每一個點都作一遍bfs求得當前點到達每一個點的最少步數。
這個是
的。
而後處理出f數組。
這個是
的。
而後,咱們就每次把多個k給or起來,變成一個全新的數組,統計答案便可。
這個是
的。
因此加起來時間過得去。
然鵝pascal作一遍
就時間炸了。
我想靜靜。spa
C++的:code
using namespace std; #include <cstdio> #include <cstring> #include <algorithm> #include <bitset> int n,m,Q; int ed[1000][1000]; int ne[10000]; struct Node{int x,s;} q[10000]; int vis[10000],nv; bitset<1000> f[1000][1000],ans; int maxdis[1000]; int main(){ freopen("center.in","r",stdin); freopen("center.out","w",stdout); scanf("%d%d%d",&n,&m,&Q); for (int i=1;i<=m;++i) { int u,v; scanf("%d%d",&u,&v),--u,--v; ed[u][v]=1; ed[v][u]=1; } for (int i=0;i<n;++i) { for (int j=0;j<n;++j) { if (ed[i][j]) { ed[i][ne[i]++]=j; } } } for (int i=0;i<n;++i) { ++nv; vis[i]=nv; f[i][0][i]=1; int h=-1,t=0; q[0]={i,0}; do { ++h; int u=q[h].x; for (int j=0;j<ne[u];++j) { int to=ed[u][j]; if (vis[to]^nv) { q[++t]={to,q[h].s+1}; vis[to]=nv; f[i][q[t].s][to]=1; } } } while (h^t); maxdis[i]=q[t].s; for (int j=1;j<=maxdis[i];++j) { f[i][j]|=f[i][j-1]; } } while (Q--) { int K; scanf("%d",&K); ans.reset(); while (K--) { int x,len; scanf("%d%d",&x,&len),--x; len=min(maxdis[x],len); ans|=f[x][len]; } printf("%d\n",ans.count()); } return 0; }
pascal的:orm
{$inline on} uses math; const up=1000; type new=record x,step:longint; end; var i,j,k,l,n,m,q,tot,ans,head,tail,took,x,y,st,long,start:longint; p:int64; a:array[1..2000*up] of new; bz:array[1..up] of boolean; cd:array[1..up] of longint; tov,next,last:array[1..200000] of longint; f:array[1..up,0..up,0..20] of int64; em:array[0..20] of int64; mi:array[0..63] of int64; map:array[1..up,1..up] of boolean; procedure bfs(dep:longint);inline; var i,j,k,l,st,step:longint; begin st:=a[dep].x; step:=a[dep].step; for i:=1 to n do begin if map[st,i] then begin if bz[i] then begin inc(took); a[took].x:=i; a[took].step:=step+1; cd[i]:=step+1; bz[i]:=false; j:=i; k:=1; while j>=63 do begin j:=j-63; k:=k+1; end; inc(f[start,step+1,k],mi[j]); end; end; end; end; begin assign(input,'center.in');reset(input); assign(output,'center.out');rewrite(output); readln(n,m,q); for i:=1 to m do begin readln(x,y); map[x,y]:=true; map[y,x]:=true; end; mi[0]:=1; for i:=1 to 62 do begin mi[i]:=mi[i-1]*2; end; for i:=1 to n do begin head:=1; tail:=1; took:=1; a[1].x:=i; a[1].step:=0; fillchar(bz,sizeof(bz),true); fillchar(cd,sizeof(cd),0); bz[i]:=false; start:=i; k:=1; j:=i; while j>=63 do begin j:=j-63; inc(k); end; f[i,0,k]:=mi[j]; repeat for j:=head to tail do begin bfs(j); end; head:=tail+1; tail:=took; until head>tail; for j:=1 to n do begin for k:=1 to 20 do begin f[i,j,k]:=f[i,j,k] or f[i,j-1,k]; end; end; end; for i:=1 to q do begin read(k); fillchar(em,sizeof(em),0); for j:=1 to k do begin read(st,long); for l:=1 to 16 do begin em[l]:=em[l] or f[st,long,l]; end; end; ans:=0; for l:=1 to 16 do begin p:=em[l]; while p>0 do begin if p mod 2=1 then inc(ans); p:=p div 2; end; end; writeln(ans); end; end.