十连测d1T3

在比特镇一共有 n 个街区,编号依次为 1 到 n,它们之间通过若干条单向道路连接。
比特镇的交通系统极具特色,除了 m 条单向道路之外,每个街区还有一个编码 vali,不同街区可能
拥有相同的编码。如果 vali and valj = valj,即 vali 在二进制下与 valj 做与运算等于 valj,那么也会
存在一条额外的从 i 出发到 j 的单向道路。
Byteasar 现在位于 1 号街区,他想知道通过这些道路到达每一个街区最少需要多少时间。因为比特
镇的交通十分发达,你可以认为通过每条道路都只需要 1 单位时间。
Input
第一行包含两个正整数 n; m,表示街区的总数以及道路的总数。
第二行包含 n 个正整数 val1; val2; :::; valn,分别表示每个街区的编码。
接下来 m 行,每行包含两个正整数 ui; vi,表示一条单向道路,起点为 ui,终点为 vi。
Output
输出 n 行,每行一个整数,其中第 i 行输出到达第 i 个街区的最少时间,如果无法到达则输出 −1。
Examples
walk.in
5 2
5 4 2 3 7
1 4
2 3
walk.out
0
1
2
1
-1

思路:个人理解为一个二分图
val值: 1 2 3 ……….2^20-1 2^20 ——————(1)

n个点: 2^20+1 2^20+2 ……….2^20+n ———(2)

所有(2)向(1)建的边为1,所有(1)向(2)建的边为0
同时所有(1)在寻找过程中暴力枚举子集即可

program df;
type point=^node;
node=record
date,ends:longint;
next:point;
end;
tttt=array[0..2000000] of point;
var i,n,m,x,y,z,k,t,h:longint;
path,pa:tttt; j:point; // path指的是连接长度为1的,pa指的是连接长度为0的
a,d,q:array[0..2000000] of longint;
b:array[0..2000000] of boolean;
procedure com(x,y:longint; var a:tttt);
var i:point;
begin
i:=a[x];
new(a[x]);
a[x]^.ends:=y;
a[x]^.next:=i;
end;

procedure deal(x,y:longint);
var i:point;
j:longint;
begin
if d[x]>=0 then exit;
inc(t);
q[t]:=x; //入队
d[q[t]]:=y;
i:=pa[x];
while i<>nil do
begin
j:=i^.ends;
deal(j,y); //所有当前val值能到达的点都与当前的点权值相同
i:=i^.next;
end;
if x>=z then exit; //如果超过val值的最大范围就不属于val值,同样没必要找子集
for j:=1 to 20 do
if x>>(j-1) and 1=1 then deal(x xor (1<<(j-1)),y); //每一位为1的都取反(即子集)
end;

begin
assign(input,’walk.in’);
reset(input);
assign(output,’walk.out’);
rewrite(output);
readln(n,m);
z:=1<<20; //将1到2^20 作为val值,n个点排到2^20+1到2^20+n
for i:=1 to n do
begin
read(x);
com(i+z,x,path); //第i个点向val值为x的点连接一条为1的边
com(x,i+z,pa); //val值为x的点向能到的点连接一条为0的边
end;
for i:=1 to m do
begin
readln(x,y);
com(x+z,y+z,path); //x,y间直接建边
end;

for i:=1 to n+z do
d[i]:=-1;
h:=1; t:=0;
deal(z+1,0); //从第一个点出发
while h<=t do
begin
x:=q[h];
j:=path[x];
while j<>nil do
begin
deal(j^.ends,d[x]+1); // x点到达的点距离加+1
j:=j^.next;
end;
inc(h);
end;
for i:=z+1 to z+n do
writeln(d[i]);

close(input);
close(output);
end.

转载于:https://www.cnblogs.com/Gxyhqzt/p/7784226.html

//// 1. st边沿检 //reg st_d1; //wire st_posedge = clk_st & ~st_d1; // 上升沿 //wire st_negedge = ~clk_st & st_d1; // 下降沿 // //always @(posedge clk_sensor or negedge reset_n) begin // if (!reset_n) // st_d1 <= 1&#39;b1; // 初始值匹配需求 // else // st_d1 <= clk_st; // 延迟1拍用于边沿检 //end // //// 2. active区间标记(st上升沿到下降沿) //reg active; //always @(posedge clk_sensor or negedge reset_n) begin // if (!reset_n) // active <= 1&#39;b0; // else if (st_posedge) // active <= 1&#39;b1; // else if (st_negedge) // active <= 1&#39;b0; //end // //// 3. 关键:仅用1级寄存器实现“st上升沿后延迟1个周期启动” //// 去掉trig_delay1和start两级寄存器,合并为start_reg //reg start_reg; // 替代trig_delay1 + start,仅1级延迟 //reg [7:0] cnt_total; //always @(posedge clk_sensor or negedge reset_n) begin // if (!reset_n) // start_reg <= 1&#39;b0; // else if (st_posedge) // st上升沿时,下一个周期启动(延迟1个周期) // start_reg <= 1&#39;b1; // else if (cnt_total == 8&#39;d255) // 256个周期后关闭 // start_reg <= 1&#39;b0; //end // //reg [1:0] cnt_cycle; //always @(posedge clk_sensor or negedge reset_n) begin // if (!reset_n) // cnt_cycle <= 2&#39;d0; // else if (st_posedge) // cnt_cycle <= 2&#39;d0; // else if (!start_reg || !active) // cnt_cycle <= 2&#39;d0; // else if (start_reg && active) // 新增有效条件 // cnt_cycle <= (cnt_cycle == 2&#39;d3) ? 2&#39;d0 : cnt_cycle + 2&#39;d1; //end // //// 5. 总周期计数器(0-255,记录256个周期) // //always @(posedge clk_sensor or negedge reset_n) begin // if (!reset_n) // cnt_total <= 8&#39;d0; // else if (!start_reg || !active) // 用start_reg直接控制 // cnt_total <= 8&#39;d0; // else if (cnt_cycle == 2&#39;d3) // 每4个clk_sensor完成1个周期 // cnt_total <= cnt_total + 8&#39;d1; //end // //// 6. clk_video输出逻辑(启动延迟精准控制) //always @(posedge clk_sensor or negedge reset_n) begin // if (!reset_n) // clk_video <= 1&#39;b0; // else if (!active) // clk_video <= 1&#39;b0; // // 仅在start_reg有效且未完成256个周期时输出 // else if (start_reg && cnt_total < 8&#39;d255) // clk_video <= (cnt_cycle < 2&#39;d2) ? 1&#39;b1 : 1&#39;b0; // 2高2低 // else // clk_video <= 1&#39;b0; //end 这段代码的的功能,除了video信号的发生时间要调到ST信号的上升沿,其他周期,宽度之类的保持不变
最新发布
07-12
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值