單詞化日記 留言簿 主頁

编程语言排名(TIOBE Programming Community Index)

TIOBE编程语言排行榜给出了各种编程语言的流行趋势。排行榜每月更新一次。TIOBE排名的计算基于全世界范围内技艺高超的工程师,课程和第三方供应商对各种编程语言的使用率。最流行的搜索引擎Google,MSN,Yahoo都被用于计算TIOBE排名的计算。但是,TIOBE排名并不是为了衡量哪种编程语言最好或者是用哪种编程语言写出来的代码最多。

TIOBE排名是用来检查你所掌握的语言技巧是否足够好,能够让你正确地选择采用哪种语言做开发。

下表是2008年5月编程语言的前20名:

space

 

长期趋势

下面的图表给出了排名前10的程序语言的长期流行趋势。

  space2

其他编程语言

以下列出了排名前50的全部的编程语言。但这只是非正式的发布,因为我们可能遗漏了某一种语言。

space3

space4

 

排名50以后的编程语言

下面列出了排名51到100的50种语言。因为它们之间的比率差异相对来说比较小,所以这里只是简单地罗列出来(以字母表的顺序)。

ABC,AD,Alpha,Applescript,AspectJ,Beta,Boo,cg,Ch,Clean,Csh,Curl,DC, Dylan,Eiffel,Euphoria,F#,Factor,Felix,Focus,Groovy,Inform,Io,J#,Lasso, MAD,Magic,Maple,Mathematica,MOO,MUMPS,Occam,OPL,Oz,PILOT,Postscript, Powerbuilder,Progress,Q,REALbasic,Revolution,S-lang,Scala,Seed7,SIGNAL, SPSS,Verilog,VHDL,Whitespace,XSLT

 

居然神奇的在这个排名表中发现了Whitespace,呵呵

 

原文链接:http://www.tiobe.com/index.htm?tiobe_index

Tags: ,

另一种神奇的Whitespace语言

Whitespace是由Durham大学的Wdwin Brady和Chris Morris发明的,于2003年4月1日发布(和愚人节有关?)。和大多数语言通常忽略空白字符不同,Whitespace解释器忽略一切非空白字符。空格、Tab和换行是仅有的语法元素。这就带来了一个有趣的事实:一个Whitespace程序可以完美地嵌入进一个文章之中。
Whitespace是一种命令式堆栈型语言,程序运行在一个有一个栈(Stack)和一个堆(Heap)的虚拟机之上。编程者可以将任意大小的整数压入栈中(目前还没有实现对浮点数的操作)。堆常用作存储变量和数据结构的固定存储空间,用户可以直接访问。 数字和字母(ASCII)都用二进制表示,空格表示0,Tab表示1。你可以在这里看到详细的教学。
很多人会问,这个有什么用呢?
确实没啥用。不过也确实很好玩。根据它的特点怎么也能编出一些不太靠谱儿的“用途”来。比如,和BrainFuck一样,这种语言要写注释就方便了,写的注释根本不需要标识,编译器直接跳过你写的文字信息。还有,我们完全可以在满篇空白的代码中插入一篇文章,从而在看起来完全无关的文章中隐藏一段代码。对于间谍工作来说这种语言帮助很大,因为它可以防止别人把代码打印出来拿走 -_-|||
Whitespace已经被证明是图灵完备的。证明可以在主页的邮件列表中找到,其晦涩程度之大,目前还没有人对证明作出评论。下面是Hello World程序:

 
Whitespace  
 
 

Tags: ,

神奇的BrainF**k语言

先介绍下BrainF**k:

Brainf**k is the ungodly creation of Urban Müller, whose goal was apparently to create a Turing-complete language for which he could write the smallest compiler ever, for the Amiga OS 2.0. His compiler was 240 bytes in size. (Though he improved upon this later -- he informed me at one point that he had managed to bring it under 200 bytes.)

BrainF**k 语言,是一种按照“Turing complete”思想设计的语言,它的主要设计思路是:用最小的概念实现一种“简单”的语言,BrainFuck 语言只有八种符号,所有的操作都由这八种符号的组合来完成。

>
Increment the pointer.

<
Decrement the pointer.

+
Increment the byte at the pointer.

-
Decrement the byte at the pointer.

.
Output the byte at the pointer.

,
Input a byte and store it in the byte at the pointer.

[
Jump forward past the matching ] if the byte at the pointer is zero.

]
Jump backward to the matching [ unless the byte at the pointer is zero.

>       指针加一
<         指针减一
+         指针指向的字节的值加一
- 指针指向的字节的值减一
. 输出指针指向的单元内容(ASCII码)
, 输入内容到指针指向的单元(ASCII码)
[ 如果指针指向的单元值为零,向前跳转到对应的]指令的次一指令处
] 如果指针指向的单元值不为零,向后跳转到对应的[指令的次一指令处

因为 BrainFuck 只有八种指令,并且没有关键字,也不允许自定义标识符,
因此它的编译器实现起来非常简单,初学 C 语言不久的人都可以自己编出来,尽管在座的各位每人都可以自己编一个,不过为了引起大家的兴趣,我这里还是给出大家一个官方发布的版本:

CODE:

#include <stdio.h>;
int   p, r, q;
char a[5000], f[5000], b, o, *s=f;
void interpret(char *c)
{
char *d;
r++;
while( *c ) {
//if(strchr("<>;+-,.[]\n",*c))printf("%c",*c);
switch(o=1,*c++) {
case '<': p--;        break;
case '>;': p++;        break;
case '+': a[p]++;     break;
case '-': a[p]--;     break;
case '.': putchar(a[p]); fflush(stdout); break;
case ',': a[p]=getchar();fflush(stdout); break;
case '[':
for( b=1,d=c; b && *c; c++ )
b+=*c=='[', b-=*c==']';
if(!b) {
c[-1]=0;
while( a[p] )
interpret(d);
c[-1]=']';
break;
}
case ']':
puts("UNBALANCED BRACKETS"), exit(0);
case '#':
if(q>;2)
printf("%2d %2d %2d %2d %2d %2d %2d %2d %2d %2d\n%*s\n",
          *a,a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8],a[9],3*p+2,"^");
break;
default: o=0;
}
if( p<0 || p>;100)
puts("RANGE ERROR"), exit(0);
}
r--;
// chkabort();
}
main(int argc,char *argv[])
{
FILE *z;
q=argc;
if(z=fopen(argv[1],"r")) {
while( (b=getc(z))>;0 )
*s++=b;
*s=0;
interpret(f);
}
}

 

再贴点BF程序:

“Hello World”程序:

>+++++++++[<++++++++>-]<.>+++++++[<++++>-]<+.+++++++..+++.[-]>+

+++++++[<++++>-]<.>+++++++++++[<+++++>-]<.>++++++++<+++>-]<.+

++.------.--------.[-]>++++++++[<++++>-]<+.[-]++++++++++.

 

==============头昏脑胀的分割线 ^-^================

 

怎样,这个语言很牛X吧?但更牛X的是.下面这个程序则允许用户输入一个数字然后程序将输出小于这个数字的所有质数。

>++++++++[<++++++++>-]<++++++++++++++++.[-]>++++++++++[<+++

+++++++>-]<+++++++++++++.[-]>++++++++++[<++++++++++>-]<+++++

.[-]>++++++++++[<++++++++++>-]<+++++++++.[-]>++++++++++[<++++

++++++>-]<+.[-]>++++++++++[<++++++++++>-]<+++++++++++++++.[-]>

+++++[<+++++>-]<+++++++.[-]>++++++++++[<++++++++++>-]<+++++++

++++++++++.[-]>++++++++++[<++++++++++>-]<++++++++++++.[-]>+++

++[<+++++>-]<+++++++.[-]>++++++++++[<++++++++++>-]<+++++++++

++++++.[-]>++++++++++[<++++++++++>-]<+++++++++++.[-]>+++++++[

<+++++++>-]<+++++++++.[-]>+++++[<+++++>-]<+++++++.[-]+[->,----------

[<+>-------------------------------------->[>+>+<<-]>>[<<+>>-]<>>>+++++++++[<

<<[>+>+<<-]>>[<<+>>-]<[<<+>>-]>>-]<<<[-]<<[>+<-]]<]>>[<<+>>-]<<>+<-

[>+[>+>+<<-]>>[<<+>>-]<>+<-->>>>>>>>+<<<<<<<<[>+<-<[>>>+>+<<<

<-]>>>>[<<<<+>>>>-]<<<>[>>+>+<<<-]>>>[<<<+>>>-]<<<<>>>[>+>+<<-]

>>[<<+>>-]<<<[>>>>>+<<<[>+>+<<-]>>[<<+>>-]<[>>[-]<<-]>>[<<<<[>+>+

<<-]>>[<<+>>-]<>>>-]<<<-<<-]+>>[<<[-]>>-]<<>[-]<[>>>>>>[-]<<<<<<-]<

<>>[-]>[-]<<<]>>>>>>>>[-<<<<<<<[-]<<[>>+>+<<<-]>>>[<<<+>>>-]<<<>>

[>+<-]>[[>+>+<<-]>>[<<+>>-]<>++++++++<[>>>+<<[>+>[-]<<-]>[<+>-]>[<

<++++++++++>>-]<<-<-]+++++++++>[<->-]<[>+<-]<[>+<-]<[>+<-]>>>[<<<

+>>>-]<>+++++++++<[>>>+<<[>+>[-]<<-]>[<+>-]>[<<++++++++++>>>+<-

]<<-<-]>>>>[<<<<+>>>>-]<<<<>[-]<<+>]<[[>+<-]+++++++[<+++++++>-]<-

><.[-]>>[<<+>>-]<<-]>++++[<++++++++>-]<.[-]>>>>>>>]<<<<<<<<>[-]<[-

]<<-]++++++++++.[-]

 

不知看完之后你吐了没,如果没有,建议你吃过饭后再看一遍。-____-b

Tags: ,

USACO Chapter1报告

Usaco第一章做完了,总结一下~

 

Section 1.1.1 PROB Your Ride Is Here [ANALYSIS]

这道题就是考你会不会写程序啦,还有呢,就是 ord(c) 这个Function的运用了~

 

Section 1.1.2 PROB Greedy Gift Givers [ANALYSIS]

这道题细心一点,名字对应好就不会错了~

 

Section 1.1.3 PROB Friday the Thirteenth [ANALYSIS]

这一道题的关键就是:下一个月13号的星期数就等于(这个月13号的星期数+这个月的天数MOD 7)MOD 7

PS:我记星期天为0。

 

Section 1.1.4 PROB Broken Necklace [ANALYSIS]

O(N)的算法。Dynamic Programming is good method for solving this problem in O(N).

If we consider two copies of the string we easy transform cyclic configuration of the necklace to linear.

Now we can compute for each breaking point how many beads of the same color can be collected on the left and on the right from the breaking point. I show how we can compute it only for the left side.

For right side it is analogical. Let r[p] and b[p] be the number of red / blue beads that can be collected, when necklace is broken in point p. If we know this and color of next bead (c) we can compute r[p+1] and b[p+1].

r[0] = p[0] = 0 If c = 'r' then r[p+1] = r[p] + 1 and b[p+1] = 0 because the length of the blue beads is 0.

if c = 'b' then b[p+1] = b[p] + 1 and r[p+1] = 0if c = 'w' then both length of the red and length of blue beads canbe longer. so r[p+1] = r[p]+1 and b[p+1] = b[p] + 1.

The number of beads that can be collected in breaking point p is then

max(left[r[p]], left[b[p]]) + max(right[r[p]], right[b[p]]).

And themaximum from this value is answer for the problem.

PS:我是看了标程写出来的呃~做了好久,原来的烦死掉了,就重写了一个。先把珠子复制一遍~

 

Section 1.2.1 PROB Milking Cows [ANALYSIS]

先按起始时间进行快速排序,然后按顺序判断时间段
if t1[i]<=r then
r:=max(t2[i],r)
t1[i],t2[i]为每一位工人的起始结束时间。
l、r为时间段的起始结束时间。
每一个连续的时间段结束后。
a1:=max(a1,r-l);
a2:=max(a2,t1[i]-r);
l:=t1[i];
r:=t2[i];
a1为最长的连续工作时间;
a2为最长的空闲时间;
最后再执行一次求最长的连续工作时间 a1:=max(a1,r-l);
完成~

 

Section 1.2.2 PROB Transformations [ANALYSIS]

这道题,好奇怪厄~主程序都一样,原来的就是提交不通过~呃~郁闷的~Procedure N4 为翻转Procedure N1 为顺时针90'最后再用 function bj 来判断两图案是否相同~

procedure N1(l:arr2; var m:arr2);

var i,j:integer;

begin

for i:=1 to n do

for j:=1 to n do

m[j,n-i+1]:=l[i,j];

end;

function bj(a,b:arr2):boolean;

var i,j:integer;

begin

equal:= true;

for i:=1 to n do

for j:=1 to n do

if a[i,j] <> b[i,j] then begin

equal:=false; exit;

end;

end;

 

Section 1.2.3 PROB Name That Number [ANALYSIS]

掌握好文件的读取写入操作,逐个读入字典中的人名,并转换成数字,与起始的数字比较,相同就输出,全部用字符串,不知道为什么我用int64和longint都不可以。厄~一开始想把数字转换成名字作但复杂度为O(3^N),太复杂,后来看了别人的报告,发觉用字典好~

s:array['A'..'Z'] of char=('2','2','2','3','3','3','4','4','4','5','5','5', '6','6','6','7','7','7','7','8','8','8','9','9','9','9');

 

Section 1.2.4 PROB Palindromic Squares [ANALYSIS]

最主要的是进制转换。Procedure ToB 然后倒转字符串若相等,即为回文数。输出。

procedure ToB (a:longint;var c:string);

var k,i:longint;

begin

k:=0;

c:='';

repeat inc(k);

i:=a mod b;

a:=a div b;

c:=s[i]+c;

until a=0;

end;

 

Section 1.2.5 PROB Dual Palindromes [ANALYSIS]

和上一道差不多 TOB +倒转字符串 轻松AC

 

Section 1.3.1 PROB Mixing Milk [ANALYSIS]

我先用快排Qsort把所有数据排序,每次选最小的卖牛奶的人把他“榨干”,求出钱数~ 贪心第一题

 

Section 1.3.2 PROB Barn Repair [ANALYSIS]

~~~好汗的~已经是第三道关于牛的了呃~
第一次数据太弱,程序完全错掉还AC3个,汗
先读入全部数据,进行快排。
然后把满牛棚之间的连续的空牛棚的数量存入数组,进行快排~
舍去最大的M-1个数字~
剩下的加上C即为最终解~ 还是贪心

 

Section 1.3.3 PROB Calf Flac [ANALYSIS]

三个数组~a为原文c为a中的字母,转为大写存入~b为c中字母在a中对应的位置,最后输出时使用~

 

Section 1.3.4 PROB Prime Cryptarithm [ANALYSIS]

厄~一开始没看清题目~以为最后输出的数为回文数~汗~USACO的题目太奇怪了~做到现在不是回文数就是COW呃~思维定势~别的就没有什么叻~枚举第一行,第二行的每一种可能性,使3,4,5行都满足条件~

 

Section 1.4.1 PROB Packing Rectangles [ANALYSIS]

郁闷死了,从开学做到现在,不爽 ,Copy lhyxxh1 同学的,

这道题目数据规模很小,大可枚举4个矩形的摆放方式,然后再计算大矩形的边长。
以下用width[1..4]表示矩形的长,height[1..4]表示矩形的宽。用w表示大矩形的长,h表示大矩形的宽:
方式一:
w = width[1] + width[2] + width[3] + width[4]
h = MAX{height[1], height[2], height[3], height[4]}
方式二:
w = MAX{width[1] + width[2] + width[3], width[4]}
h = MAX{height[1], height[2], height[3]} + height[4]
方式三:
w = MAX{width[1] + width[2], width[3]} + width[4]
h = MAX{MAX{height[1], height[2]} + height[3], height[4]}
方式四:
w = width[1] + width[2] + MAX{width[3], width[4]}
h = MAX{height[1], height[2], height[3] + height[4]}
方式五:
同方式四。
方式六:
h = MAX{height[1] + height[3], height[2] + height[4]}
w = MAX: width[1] + width[2], 一般条件
width[3], 一般条件
width[4], 一般条件
width[2] + width[3], 当height[1] < height[2]时
width[1] + width[4], 当height[1] > height[2]时
width[3] + width[4], 当height[1] + height[3] > height[2]时
注意以上是把矩形1放到左下,2放到右下,3放到右上,4放到左上为例的。

 

Section 1.4.2 PROB The Clocks [ANALYSIS]

枚举所有方法

还有一种Ox的

program clocks;
const
INV : array[3..12] of byte =(1, 0, 0, 2, 0, 0, 3, 0, 0, 0);

var inp, out: text;
a, b, c, d, e, f, g, h, i: integer;
ax, bx, cx, dx, ex, fx, gx, hx, ix,l: integer;
t,an: array[1..9] of integer;
begin
assign (inp, 'clocks.in'); reset (inp);
readln(inp, ax, bx, cx);
readln(inp, dx, ex, fx);
readln(inp, gx, hx, ix);
a:=inv[ax]; b:=inv[bx]; c:=inv[cx]; d:=inv[dx];
e:=inv[ex]; f:=inv[fx]; g:=inv[gx]; h:=inv[hx];
i:=inv[ix];
t[1] := ( 8 + a + 2 * b + c + 2 * d +2 * e - f + g - h ) mod 4;
t[2] := ( a + b + c + d + e + f + 2 * g + 2 * i ) mod 4;
t[3] := ( 8 + a + 2 * b + c - d + 2 * e + 2 * f -h + i ) mod 4;
t[4] := ( a + b + 2 * c + d + e + g + h + 2 * i ) mod 4;
t[5] := ( 4 + a + 2 * b + c + 2 * d - e + 2 * f + g + 2 * h+ i ) 
mod 4;
t[6] := ( 2 * a + b + c + e + f + 2 * g + h + i ) mod 4;
t[7] := ( 8 + a - b + 2 * d + 2 * e - f + g + 2 * h + i ) mod 4;
t[8] := ( 2 * a + 2 * c + d + e + f + g + h + i) mod 4;
t[9] := ( 8 - b + c - d + 2 * e + 2 * f + g + 2 * h+ i) mod 4;
assign(out, 'clocks.out'); rewrite(out);
for a := 1 to 9 do
for b := 1 to t[a] do Begin
inc(l);
an[l]:=a;
end;
for a:=1 to l-1 do
write(out,an[a],' ');
write(out,an[l]);
writeln(out); close(out)
end.
 

Section 1.4.3 PROB Arithmetic Progressions [ANALYSIS]

说实话,没看懂是怎么做的~

 

Section 1.4.4 PROB Mother's Milk [ANALYSIS]

说实话,没看懂是怎么做的~

 

Section 1.5.1 PROB Number Triangles [ANALYSIS]

dp[i,j]:=max(dp[i-1,j],dp[i-1,j-1])+tree[i,j];

dp为到该节点的最大权值,tree为该点权值

动规?

 

Section 1.5.2PROB Prime Palindromes [ANALYSIS]

判断素数

function prime(z:longint):boolean;

var

i:longint;

begin

begin

i:=2;

while (i*i<=z) and (z mod i <>0) do inc(i);

if z mod i = 0 then prime:=false else prime:=true;

end;

end;

还有就是符合条件的偶数位的数只有11(可以证明) 从三位数搜索吧(<100 的只有 5 7 11)

 

Section 1.5.3PROB SuperPrime Rib [ANALYSIS]

procedure sp(x,k:longint);

var

i:longint;

begin

if k<=n then

for i:=1 to 4 do begin

x:=x*10+y[i];

if prime(x) then sp(x,k+1);

x:=(x-y[i]) div 10;

end

else

writeln(x);

end;

x为当前数 k为当前数的长度 DFS 搜吧

 

Section 1.5.4PROB Checker Challenge [ANALYSIS]

经典的8皇后问题,小于11的我能通过,大的就TLE了~

 

就这样吧~先更新到这里了~

BY Wandsea 转载请注明~

Tags:

Flood Fill 种子染色法

Flood Fill 按原意应翻译成“水流式填充法”(如果我没译错),有些中文书籍上将它称作“种子染色法”,然而大部分的书籍(包括中文书籍)都直接引用其英文原名:Flood Fill。介于此,下文所有涉及到Flood Fill的都直接引用英文 ——译者)

样例: 相连的农场

Farmer John的农场被一次意外事故破坏了,有一些农场与其他的农场之间有道路相连,而有些道路却已被破坏。这使得Farmer John 无法了解到从一个农场能否到达另一个农场。你的任务就是帮助Farmer John来了解哪些农场是连通的。

给出:

上题实际上就是要求寻找一张无向图的所有极大连通子图。

给出一张未知连通性的图,如下图:


可知,该图的极大连通子图是:{1,4,8}, {2,5,6,7,9} 和 {3}。

算法: Flood Fill

Flood Fill 可以用深度优先搜索,广度优先搜索或广度优先扫描来实现。他的实现方式是寻找到一个未被标记的结点对它标记后扩展,将所有由它扩展出的结点标上与它相同的标号,然后再找另一个未被标号的 结点重复该过程。这样,标号相同的结点就属于同一个连通子图。

深搜:取一个结点,对其标记,然后标记它所有的邻结点。对它的每一个邻结点这么一直递归下去完成搜索。

广搜:与深搜不同的是,广搜把结点加入队列中。

广度扫描(不常见):每个结点有两个值,一个用来记录它属于哪个连通子图(c),一个用来标记是否已经访问(v)。算法对每一个未访问而在某个连通子图当中的结点扫描,将其标记访问,然后把它的邻结点的(c)值改为当前结点的(c)值。

深搜最容易写,但它需要一个栈。搜索显式图没问题,而对于隐式图,栈可能就存不下了。

广搜稍微好一点,不过也存在问题。搜索大的图它的队列有可能存不下。深搜和广搜时间复杂度均为O(N+M)。其中,N为结点数,M为边数。

广度扫描需要的额外空间很少,或者可以说根本不要额外空间,但是它很慢。时间复杂度是O(N^2+M)。

(实际应用中,我们一般写的是DFS,因为快。空间不是问题,DFS可改用非递归的栈操作完成。但为了尊重原文,我们还是译出了广度扫描的全过程。——译者)

广度扫描的伪代码

代码中用了一个小技巧,因此无须额外空间。结点若未访问,将其归入连通子图(-2),就是代码里的component -2。这样无须额外空间来记录结点是否访问,请读者用心体会。

# component(i) denotes the
# component that node i is in
1 function flood_fill(new_component)

2 do
3 num_visited = 0
4 for all nodes i
5 if component(i) = -2
6 num_visited = num_visited + 1
7 component(i) = new_component
8 for all neighbors j of node i
9 if component(j) = nil
10 component(j) = -2
11 until num_visited = 0

12 function find_components

13 num_components = 0
14 for all nodes i
15 component(node i) = nil
16 for all nodes i
17 if component(node i) is nil
18 num_components =
num_components + 1
19 component(i) = -2
20 flood_fill(component
num_components)

算法的时间复杂度是 O(N 2),每个结点访问一次,每条边经过两次。

实例

考虑刚才的那张图:

开始时,所有的结点都没有访问。(下例中未访问被表示为 -2)

首先从结点1开始,结点1未访问,那么先处理结点1,将它归入连通子图1。

结点 连通子图
1 -2

标记完成后,对它进行第一步的扩展,由结点4和结点8与结点1连通,故它们被扩展出来。

结点 连通子图
1 1
4 -2
8 -2

之后,先处理结点4,将它与结点1归入相同的连通子图。现在它没有可扩展的结点了(结点1已被扩展过)

结点 连通子图
1 1
4 1
8 -2

接着处理结点8。结果与结点4一样。

结点 连通子图
1 1
4 1
8 1

现在,所有与结点1连通的结点都已扩展,标号为1的连通子图产生了。那么我们将跳出扩展步骤,寻找下一个连通子图,标号为2。

与上一步相同的顺序,找到结点2。

结点 连通子图
1 1
2 -2
4 1
8 1

扩展结点2,结点7与结点9出现。

结点 连通子图
1 1
2 2
4 1
7 -2
8 1
9 -2

下一步,扩展结点7,结点5出现。

结点 连通子图
1 1
2 2
4 1
5 -2
7 2
8 1
9 -2

然后是结点9。

结点 连通子图
1 1
2 2
4 1
5 -2
7 2
8 1
9 2

扩展结点5。结点6出现。

结点 连通子图
1 1
2 2
4 1
5 2
6 -2
7 2
8 1
9 2

很遗憾,结点6没有可供扩展的结点。至此连通子图2产生。

结点 连通子图
1 1
2 2
4 1
5 2
6 2
7 2
8 1
9 2

之后寻找连通子图3,至此,仅有结点3未被扩展。

结点 连通子图
1 1
2 2
3 -2
4 1
5 2
6 2
7 2
8 1
9 2

结点3没有可供扩展的结点,这样,结点3就构成了仅有一个结点的连通子图3。

结点 连通子图
1 1
2 2
3 3
4 1
5 2
6 2
7 2
8 1
9 2

结点3处理结束后,整个图的所有9个结点就都被归入相应的3个连通子图。Flood Fill 结束。

问题提示

这类问题一般很清晰,求解关于“连通”的问题会用到 Flood Fill。它也很经常用作某些算法的预处理。

扩展与延伸

有向图的连通性比较复杂。

同样的填充算法可以找出从一个结点能够到达的所有结点。每一层递归时,若一个结点未访问,就将其标记为已访问(表示他可以从源结点到达),然后对它所有能到达且为访问的结点进行下一层递归。

若要求出可以到达某个结点的所有结点,你可以对后向弧做相同的操作。

例题

控制公司 [有删节, IOI 93]

已知一个带权有向图,权值在0-100之间。

如果满足下列条件,那么结点A“拥有”结点B:

  • A = B

  • 从A到B有一条权值大于50的有向弧。

  • 存在一系列结点 C 1C k 满足 A 拥有 C 1C k, 每个节点都有一条弧到B,记作x 1 ,x 2 ...x k,并且 x 1 + x 2 + ... + x k > 50。

找出所有的(A,B)对,满足A拥有B。

分析:这题可以用上面提到的“给出一个源,在有向图中找出它能够到达的结点”算法的改进版解决。要计算A拥有的结点,要对每个结点计算其“控股百分比”。 把它们全部设为0。现在,

Tags: ,

  • Google Adsense

  • 訂閱我

  • G-Readers

  • My Links