jzoj5932. 【NOIP2018模擬10.27】情報中心

Description

題目背景
。飛紛火戰來年近國 D 和國 C
。飛亂子鴿來年近國 D 和國 C
題面描述
最近,C 國成功地滲透進入了 D 國的一個城市。這個城市能夠抽象成一張有 n 個節點,節點之間有 m 條雙向道路鏈接的無向圖,每條道路的⻓度都爲 1 。
通過偵查,C 國情報部部⻓ GGB 驚訝地發現,這座看起來不起眼的城市居然是 D 國的軍事中心。所以 GGB 決定在這個城市內設立情報機構。情報專家 TAC 在偵查後,安排了 q 種設立情報機構的方案。這些方案中,第 i 種方案將計劃創建 ki 個情報機構,第 j 個情報機構能夠安排人員到距離其不超過 di,j 的節點上收集情報。html

Input

從文件 center.in 中讀入數據。
輸入第一行包含三個正整數 n, m, q ,分別表示城市的節點個數、道路條數和方案個數。
接下去 m 行每行兩個正整數 u, v ,表示存在一條鏈接城市 u 和城市 v 的雙向道路。
接下去 q 行,每行表示一個方案。第一個正整數 k 表示該種方案將計劃創建 k 個情報機構,以後是 2k 個正整數,其中第 2i − 1 個數表示方案中第 i 個情報機構所在的節點編號,第 2i 個數表示第 i 個情報點所能派出情報人員的最遠距離。c++

Output

輸出到文件 center.out 中。
輸出包含 q 行,每行包含一個整數,表示相應詢問的答案。web

Sample Input

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數組

Sample Output

4
5
5app

Data Constraint

在這裏插入圖片描述
題目更正: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求得當前點到達每一個點的最少步數。
這個是 O ( n m ) O(n*m) 的。
而後處理出f數組。
這個是 O ( n 3 / 32 ) O(n^3/32) 的。
而後,咱們就每次把多個k給or起來,變成一個全新的數組,統計答案便可。
這個是 O ( ( k ) 32 ) O((\sum{k})*32) 的。
因此加起來時間過得去。
然鵝pascal作一遍 O ( n m ) O(n*m) 就時間炸了。
我想靜靜。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.
相關文章
相關標籤/搜索