zoukankan      html  css  js  c++  java
  • 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 的节点上收集情报。

    Input

    从文件 center.in 中读入数据。
    输入第一行包含三个正整数 n, m, q ,分别表示城市的节点个数、道路条数和方案个数。
    接下去 m 行每行两个正整数 u, v ,表示存在一条连接城市 u 和城市 v 的双向道路。
    接下去 q 行,每行表示一个方案。第一个正整数 k 表示该种方案将计划建立 k 个情报机构,之后是 2k 个正整数,其中第 2i − 1 个数表示方案中第 i 个情报机构所在的节点编号,第 2i 个数表示第 i 个情报点所能派出情报人员的最远距离。

    Output

    输出到文件 center.out 中。
    输出包含 q 行,每行包含一个整数,表示相应询问的答案。

    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
    5

    Data Constraint

    在这里插入图片描述
    题目更正:di,j值域在int范围内;q小于等于100000

    题解

    这题额,只有一个评价——语言歧视,不要脸。
    首先,我们一个直观的想法——
    f[i,j,k]表示第i个点,走了j步,能否到达k。
    然而这样子空间不保证。
    尝试把k看成一个状态。
    那么就是:
    f[i,j]表示第i个点,走了j步,能到达点的情况。
    pascal就要多加维k,把1000压成32个longint存储2进制。
    C++好像有一个叫做bitset的好家伙可以用。
    然后我们每个点都做一遍bfs求得当前点到达每个点的最少步数。
    这个是O(nm)O(n*m)的。
    然后处理出f数组。
    这个是O(n3/32)O(n^3/32)的。
    然后,我们就每次把多个k给or起来,变成一个全新的数组,统计答案即可。
    这个是O((k)32)O((sum{k})*32)的。
    所以加起来时间过得去。
    然鹅pascal做一遍O(nm)O(n*m)就时间炸了。
    我想静静。

    标程

    C++的:

    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
    ",ans.count());
    	}
    	return 0;
    }
    

    pascal的:

    {$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.
    
    
    我活在这夜里。无论周围多么黑暗,我都要努力发光!我相信着,终有一天,我会在这深邃的夜里,造就一道最美的彩虹。
  • 相关阅读:
    洛谷——P1951 收费站_NOI导刊2009提高(2)
    洛谷——P1475 控制公司 Controlling Companies
    洛谷——P1176 路径计数2
    洛谷——P1156 垃圾陷阱
    洛谷——P2734 游戏 A Game
    洛谷——P1767 家族_NOI导刊2010普及(10)
    洛谷——P1413 坚果保龄球
    Kali-linux破解LM Hashes密码
    Kali-linux分析密码
    Kali-linux密码在线破解
  • 原文地址:https://www.cnblogs.com/RainbowCrown/p/11148386.html
Copyright © 2011-2022 走看看