复杂的按钮

复杂的按钮
(button.pas/c/cpp)
【题目描述】
小K在遗迹探险时遇到了N个按钮,刚开始所有的按钮都处于开状态,小K的经验告诉他把所有的按钮都关上会有“好事”发生,可是有些按钮按下时会让其他一些已经闭合的按钮弹开。经过研究,每个按钮都对应着一个固定的弹开集合,这个按钮按下时,弹开集合中所有的按钮都会变为开状态。现在小K想知道是否能让所有的按钮变为闭合状态。如果能,打印最少步数以及方案,否则,打印“no solution”。
【输入格式】
第一行一个整数N,表示按钮的个数;
接下来N行,表示编号为1到N个按钮的弹开集合,格式为Mi,B1B2B3...BMi,表示编号为i的按钮按下时,会让编号为B1B2B3...BMi的按钮弹开(注:其中不会出现重复)
【输出格式】
如果无解,输出“no solution”;否则,第一行输出最少步数ret,第二行输出ret个数,表示按顺序按下编号为这些数的按钮就可以解决,每2个整数之间用一个空格隔开;如果有多种方案,请输出字典序最小的方案。
【样例输入】
6
2 2 3
0
2 4 5
0
0
0

【样例输出】
6
1 2 3 4 5 6

【数据规模】
对于40%的数据: 1≤N≤10;
对于100%的数据:1≤N≤30,000;令M=M1+M2+M3+...+MN,则0≤M≤1,000,000;

首先,要看出来这是个鬼畜的图论题。咋么看出来的?比方说,按钮1,不受任何按钮的牵制,更何况他的序号更小,那么肯定先按他,以后就不会再次按到他了。那么我们说第一问的答案如果有解肯定是n。为什么?举个例子,所有按钮都没牵制任何按钮,那么最少最少,也需要按n次。因为你需要的是按下每一个按钮,而每个按钮原来都是开着的,而且只能是自己按下按钮,而不是按下其他按钮导致的,所以得出ans1>=n。那么如果ans1>n,就说明n次以后肯定剩下了几个按钮,比如1,5,6。那么如果再按下1,5,6,必定又会有按钮弹起,比如2,5。那么如此反复,是永远得不到结果的,说明有解的情况ans1=n。那么再回到图论,解决第二问。如果某一个按钮不受别人牵制,那么就相当于他的入度为0嘛。那么,相应的,如果a牵制b,那么a到b就有一条有向边。那么,首先我们要按下的肯定都是入度为0的结点,然后把相应的边删了。当然,如果没有结点入度为0,那就是有环了,肯定无解了。那么,我们每次要找个入度为0且序号最小的结点,把他输出,并且修改相应边与相应的点,如此反复。那么这样的效率是n^2的,100分别想。那么,我们每次取个序号最小的,这里用了o(n)的时间,所以这里可以优下来,就是调队。每次用logn时间get,在删边的同时,判断他的子节点入度是否为0,为0则入堆。最后什么时候结束?len=0,即堆为空的时候,那么这题就解完了。

 1 var n,i,j,p,x,min,tot,t,len:longint;
 2     out_,in_,a,heap:array[0..30005] of longint;
 3     son,nxt:array[0..1000005] of longint;
 4     lnk:array[0..30005] of longint;
 5 procedure print_no;
 6 begin
 7   writeln(‘no solution‘);
 8   close(input); close(output);
 9   halt;
10 end;
11 procedure put(id:longint);
12 var i:longint;
13 begin
14   inc(len); heap[len]:=id; i:=len;
15   while (i>1) do
16   begin
17     if (heap[i>>1]>heap[i]) then
18     begin
19       heap[0]:=heap[i]; heap[i]:=heap[i>>1]; heap[i>>1]:=heap[0];
20       i:=i>>1;
21     end
22     else break;
23   end;
24 end;
25 function get:longint;
26 var fa,son:longint;
27 begin
28   get:=heap[1]; heap[1]:=heap[len]; dec(len); fa:=1;
29   while (fa<<1<=len) do
30   begin
31     if (fa<<1+1>len) or (heap[fa<<1]<heap[fa<<1+1]) then son:=fa*2
32                                                     else son:=fa*2+1;
33     if heap[fa]>heap[son] then
34     begin
35       heap[0]:=heap[fa]; heap[fa]:=heap[son]; heap[son]:=heap[0];
36       fa:=son;
37     end
38     else break;
39   end;
40 end;
41 procedure add(x,y:longint);
42 begin
43   inc(tot); son[tot]:=y; nxt[tot]:=lnk[x]; lnk[x]:=tot;
44 end;
45 begin
46   readln(n);
47   for i:=1 to n do
48   begin
49     read(out_[i]);
50     for j:=1 to out_[i] do
51     begin
52       read(x); inc(in_[x]); add(i,x);
53     end;
54   end;
55   min:=maxlongint;
56   for i:=1 to n do
57   if (in_[i]=0) then begin min:=0; put(i); end;
58   if min<>0 then print_no;
59   repeat
60     p:=get; inc(t); a[t]:=p; j:=lnk[p];
61     in_[p]:=-1;
62     while j<>0 do
63     begin
64       dec(in_[son[j]]);
65       if in_[son[j]]=0 then put(son[j]);
66       j:=nxt[j];
67     end;
68   until len=0;
69   writeln(t);
70   for i:=1 to t do write(a[i],‘ ‘);
71 end.

时间: 2024-10-21 17:17:11

复杂的按钮的相关文章

万家报账平台没有“上传文件”按钮的解决办法

在有的电脑没有"上传文件"的按钮? 第一步:首先检查浏览器设置. 第二步:找到IE的Internet选项菜单,开启菜单栏的根据下列方面找,如下图: 第三步:找到Internet选项后,点击,选择安全选项卡,并点击"自定义级别" 第四步:找到"将文件上载到服务器时包含本地目录路径"选择"启用".然后点击确定关闭IE,重启打开. 第五步:更新浏览器的flash版本.在百度中搜索"flash player官网"即

ios 键盘追加完成按钮

//键盘追加完成按钮 UIToolbar * topView = [[UIToolbar alloc]initWithFrame:CGRectMake(0, 0, 320, 30)]; [topView setBarStyle:UIBarStyleDefault]; UIBarButtonItem * btnSpace = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace

微信支付开发(APP)的各种坑,.net和iOS的各种陷阱,解决.net调用下单接口提示无权限,解决iOS跳转到微信支付页面中间只有一个确定按钮

直入主题之前,请容我吐槽一下微*的官方东西:ASDFQ%#$%$#$%^[email protected]#$%DSFQ#$%.......:吐槽玩了!大家心照就好. 要完成手机APP跳转到微信的APP进行微信支付,需要进行如下操作: 1.先去微信的开放平台(http://open.weixin.qq.com)进行开发者账号的注册. 2.新建一个APP应用,然后填写必填信息提交审核. 3.进入APP应用,在接口信息中,进行申请“获得微信支付能力”的功能,期间会提交相关的公司营业信息证明等. 通过

VC自绘按钮

看了吕鑫老师的视频,自己试着编写了一个自绘按钮控件.YuButton.h头文件如下: #pragma once   #include "afxwin.h"   class CYuButton :public CWnd   {       private:           BOOL  m_bIsDown;           BOOL  m_bIsMove;           BOOL  _bMouseTrack;//鼠标追踪状态              CString  m_s

第二百零八节,jQuery EasyUI,SplitButton(分割按钮菜单)组件

jQuery EasyUI,SplitButton(分割按钮)组件 学习要点: 1.加载方式 2.属性列表 3.方法列表 本节课重点了解 EasyUI 中 SplitButton(分割按钮)组件的使用方法,这个组件依赖 于 Menu(菜单)组件和 LinkButton(按钮)组件. 注意:SplitButton(分割按钮)组件与,MenuButton(菜单按钮)是一样的,不同是(分割按钮)组件多了一个分隔符 一加载方式 class 加载方式 <a href="javascript:void

关于Cocos2d-x中UI按钮的定义

1.要有两张不同状态的图片 2.定义一个MenuItemSprite的实例,把这两张图的Sprite实例放进MenuItemSprite的实例 3.把MenuItemSprite的实例放进Menu实例 (4.暂停按钮的这种的要把MenuItemSprite的实例再放进MenuItemToggle实例中,再把MenuItemToggle实例放进Menu实例中) 5.把Menu实例addChild到层 例子 开始游戏按钮 1 auto startNormal = Sprite::create("st

【转】Android - Button(按钮)的响应点击事件的4种写法

原文网址:http://www.yrom.net/blog/2011/12/12/android-4-onclicklistener-of-button/ Button控件setOnclickListener(View.OnClickListener listener)来接收一个点击事件的监听器 自定义一个点击事件监听器类让其实现View.OnClickListener的onClick(View v)方法 1 2 3 4 5 class MyOnClickListener implements

jsp页面做文件上传时遇到要根据登陆名按钮显示或隐藏的情况

项目遇到的情况要根据登陆的角色不同显示或隐藏按钮,因为之前没有遇到过 所以有些不知道怎么下手,百度解决了 方法如下: document.getElementById("#anniu").hide() <button id="anniu">隐藏按钮</button>

[android] 切换按钮-自定义控件

准备两张图片,按钮背景,上面的小开关 创建一个类MyToggleBtn,继承View 实现三个构造方法,传递上下文, 实现构造方法,传递Context对象,在java代码中实例化时主要使用这个 实现构造方法,传递Context对象,AttributeSet对象,在布局文件中主要使用 View对象显示在屏幕上,有几个重要步骤 1.构造方法创建对象 2.测量view的大小 onSeasure(int,int) 3.确定view的位置,view自身有一些建议权,决定权在父view手中 onLayout

Android 自定义Dialog类,并在Activity中实现按钮监听。

实际开发中,经常会用到Dialog,比如退出时候会弹出是否退出,或者还有一些编辑框也会用Dialog实现,效果图如下: 开发中遇到的问题无非在于如果在Activity中监听这个Dialog中实现的按钮,Dialog类如下,在MyDialog这个类中实现了一个LeaveMyDialogListener接口,用来实现onclick的点击事件: package com.Ieasy.Tool; import com.Ieasy.ieasyware.R; import android.app.Dialog