今天的文件夹: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 |
时间: 2024-10-27 03:17:05