[NOIP集训]10月22日

今天的文件夹:10月22日.zip

并查集、哈希表是很有意思的算法,不过更好的是,今天的题我以前都A掉了~

T1:这题最省事的是用STL库的map,然后并查集水过。当然用自己写的Hash函数通过也没有压力。

T2:注意这题不要想复杂了,题中的判断规则只有一层,没必要考虑“敌人的敌人的朋友的敌人的朋友的敌人的敌人”这类情况,直接大暴力。数据结构采用并查集,先合并朋友,然后将敌人关系存为一张图,对图中的每个点,把它的所有敌人两两合并。最后输出集合个数。

T3:按顺序打击不好处理,我们倒过来看,相当于逆序依次加入团伙。这就可以并查集模拟了,每加入一个团伙,把和它有关系的团伙合并,然后判断最大集合的大小是否超过一半。最后输出的是(总团伙数-能满足此条件的最多加入的团伙数)。

代码:

 1 #include <iostream>
 2 #include <string>
 3 #include <map>
 4 using namespace std;
 5 #define FOR(i,n) for (int i=0;i<n;i++)
 6 map<string,int> hash;
 7 int father[1000001]={0};
 8 int get_father(int x)
 9 {
10     if (father[x]==x) return x;
11                  else return get_father(father[x]);
12 }
13 void set_union(int x,int y)
14 {
15     int ls1=get_father(x),ls2=get_father(y);
16     father[ls1]=ls2;
17     return;
18 }
19 bool set_same(int x,int y)
20 {
21     return (get_father(x)==get_father(y));
22 }
23 int main()
24 {
25     freopen("cc.in","r",stdin);
26     freopen("cc.out","w",stdout);
27     int n,m,p,cnt=0;
28     cin>>n>>m>>p;
29     FOR(i,n)
30     {
31         string ls;
32         cin>>ls;
33         father[cnt]=cnt;
34         hash[ls]=cnt++;
35     }
36     FOR(i,m)
37     {
38         string ls1,ls2;
39         cin>>ls1>>ls2;
40         set_union(hash[ls1],hash[ls2]);
41     }
42     FOR(i,p)
43     {
44         string ls1,ls2;
45         cin>>ls1>>ls2;
46         if (set_same(hash[ls1],hash[ls2]))
47            cout<<"safe"<<endl;
48         else
49             cout<<"cc cry"<<endl;
50     }
51     return 0;
52 }
cc.cpp
 1 program group;
 2 type
 3     node=record
 4         data:longint;
 5         father:longint;
 6     end;
 7 var
 8     a:array[1..1000] of node;
 9     b:array[1..1000] of longint;
10     p:array[1..1000,1..1000] of integer;
11     i,j,k,l,m,n,x,y:longint;
12 procedure init();
13 var
14     i:longint;
15 begin
16     fillchar(p,sizeof(p),0);
17     for i:=1 to n do
18     begin
19         a[i].father:=i;
20         a[i].data:=i;
21     end;
22 end;
23 function find(x:longint):longint;
24 var
25     i,j,k:longint;
26 begin
27     i:=x;
28     while (a[i].father<>i) do
29         i:=a[i].father;
30     k:=i;
31     i:=x;
32     while (i<>k) do
33     begin
34         j:=a[i].father;
35         a[i].father:=k;
36         i:=j;
37     end;
38     exit(k);
39 end;
40 procedure union(x,y:longint);
41 var
42     i,j,p,q,k:longint;
43 begin
44     p:=find(x);
45     q:=find(y);
46     a[q].father:=p;
47 end;
48 begin
49     assign(input,'group.in');
50     reset(input);
51     assign(output,'group.out');
52     rewrite(output);
53     readln(n,m);
54     init();
55     for i:=1 to m do
56     begin
57         readln(k,x,y);
58         if k=1 then
59         begin
60             p[x,y]:=1;
61             p[y,x]:=1;
62         end else
63             union(x,y);
64     end;
65     for i:=1 to n do
66         for j:=1 to n do
67             if p[i,j]=1 then
68                 for k:=1 to n do
69                     if (p[j,k]=1)and(k<>i)and(find(i)<>find(k)) then
70                         union(i,k);
71     fillchar(b,sizeof(b),0);
72     for i:=1 to n do
73         inc(b[find(i)]);
74     l:=0;
75     for i:=1 to n do
76         if b[i]>0 then
77             inc(l);
78     writeln(l);
79     close(input);
80     close(output);
81 end.
group.pas
 1 program black;
 2 var
 3     father:array[1..1000] of longint;
 4     count:array[1..1000] of longint;
 5     connect:array[1..1000,1..1000] of boolean;
 6     sum:longint;
 7     n:longint;
 8     i,j,k:longint;
 9 function getfather(x:longint):longint;
10 begin
11     if father[x]=x then
12         exit(x);
13     father[x]:=getfather(father[x]);
14     exit(father[x]);
15 end;
16 procedure union(x,y:longint);
17 var
18     fx,fy:longint;
19 begin
20     fx:=getfather(x);
21     fy:=getfather(y);
22     if fx=fy then
23         exit();
24     father[fy]:=fx;
25     count[fx]:=count[fx]+count[fy];
26     count[fy]:=0;
27 end;
28 begin
29     assign(input,'black.in');
30     reset(input);
31     assign(output,'black.out');
32     rewrite(output);
33     readln(n);
34     for i:=1 to n do
35     begin
36         father[i]:=i;
37         count[i]:=1;
38     end;
39     fillchar(connect,sizeof(connect),0);
40     for i:=1 to n do
41     begin
42         read(sum);
43         for j:=1 to sum do
44         begin
45             read(k);
46             connect[i,k]:=true;
47             connect[k,i]:=true;
48         end;
49     end;
50     for i:=n downto 1 do
51     begin
52         for j:=i to n do
53         begin
54             if not(connect[i,j]) then
55                 continue;
56             union(i,j);
57         end;
58         for j:=1 to n do
59             if count[j]>n div 2 then
60             begin
61                 writeln(i);
62                 halt;
63             end;
64     end;
65     close(input);
66     close(output);
67 end.
black.pas
posted @ 2015-10-22 13:10  常可  阅读(215)  评论(0编辑  收藏  举报