【BZOJ】【1529】 【POI2005】ska Piggy banks

  本来以为是tarjan缩点……但是64MB的空间根本不足以存下原图和缩点后的新图。所以呢……并查集= =

  orz hzwer

MLE的tarjan:

 1 /**************************************************************
 2     Problem: 1529
 3     User: Tunix
 4     Language: C++
 5     Result: Memory_Limit_Exceed
 6 ****************************************************************/
 7
 8 //BZOJ 1529
 9 #include<cstdio>
10 #include<cstring>
11 #include<cstdlib>
12 #include<iostream>
13 #include<algorithm>
14 #define rep(i,n) for(int i=0;i<n;++i)
15 #define F(i,j,n) for(int i=j;i<=n;++i)
16 #define D(i,j,n) for(int i=j;i>=n;--i)
17 using namespace std;
18 const int N=1000086;
19
20 void read(int &v){
21     v=0;int sign=1; char ch=getchar();
22     while(ch<‘0‘ || ch>‘9‘) {if (ch==‘-‘) sign=-1; ch=getchar();}
23     while(ch>=‘0‘&&ch<=‘9‘){v=v*10+ch-‘0‘; ch=getchar();}
24     v*=sign;
25 }
26 /********************tamplate*******************/
27 int dfn[N],low[N],dfs_clock,SCC=0,belong[N],n;
28 int head[N],to[N],next[N],cnt;
29 void ins(int x,int y){
30     to[++cnt]=y; next[cnt]=head[x]; head[x]=cnt;
31 }
32 int t[N],ne[N],h[N];
33 void add(int x,int y){
34     t[++cnt]=y; ne[cnt]=h[x]; h[x]=cnt;
35 }
36 bool inst[N];
37 int st[N],top=0;
38 void tarjan(int x){
39     int y;
40     dfn[x]=low[x]=++dfs_clock;
41     st[top++]=x;
42     inst[x]=1;
43     for(int i=head[x];i;i=next[i]){
44         y=to[i];
45         if (!dfn[y]){
46             tarjan(y);
47             low[x]=min(low[x],low[y]);
48         }
49         else if (inst[y]) low[x]=min(low[x],dfn[y]);
50     }
51     if (dfn[x]==low[x]){
52         ++SCC;
53         for(y=0;y!=x;){
54             y=st[--top];
55             inst[y]=0;
56             belong[y]=SCC;
57         }
58     }
59 }
60 int in[N];
61 void rebuild(){
62     F(x,1,n)
63         for(int i=head[x];i;i=next[i])
64             if (belong[x]!=belong[to[i]]){
65                 add(belong[x],belong[to[i]]);
66                 in[belong[to[i]]]++;
67             }
68 }
69 /***********************************************/
70
71 int main(){
72 #ifndef ONLINE_JUDGE
73     freopen("1529.in","r",stdin);
74 #endif
75     read(n);
76     int x;
77     F(i,1,n){
78         read(x);
79         ins(x,i);
80     }
81     F(i,1,n) if (!dfn[i]) tarjan(i);
82     rebuild();
83     int ans=0;
84     F(i,1,SCC) if(in[i]==0) ans++;
85     printf("%d\n",ans);
86     return 0;
87 }

并查集:

 1 /**************************************************************
 2     Problem: 1529
 3     User: Tunix
 4     Language: C++
 5     Result: Accepted
 6     Time:908 ms
 7     Memory:4712 kb
 8 ****************************************************************/
 9
10 //BZOJ 1529
11 #include<cstdio>
12 #define rep(i,n) for(int i=0;i<n;++i)
13 #define F(i,j,n) for(int i=j;i<=n;++i)
14 #define D(i,j,n) for(int i=j;i>=n;--i)
15 using namespace std;
16 const int N=1000086;
17
18 void read(int &v){
19     v=0;int sign=1; char ch=getchar();
20     while(ch<‘0‘ || ch>‘9‘) {if (ch==‘-‘) sign=-1; ch=getchar();}
21     while(ch>=‘0‘&&ch<=‘9‘){v=v*10+ch-‘0‘; ch=getchar();}
22     v*=sign;
23 }
24 int fa[N],n;
25 int getfather(int x){
26     if (fa[x]!=x) fa[x]=getfather(fa[x]);
27     return fa[x];
28 }
29 int main(){
30     read(n);
31     int x;
32     F(i,1,n) fa[i]=i;
33     F(i,1,n){
34         read(x);
35         int f1=getfather(i),f2=getfather(x);
36         if (f1!=f2) fa[f1]=f2;
37     }
38     int ans=0;
39     F(i,1,n) if (fa[i]==i) ans++;
40     printf("%d\n",ans);
41     return 0;
42 }

时间: 2024-10-27 08:10:14

【BZOJ】【1529】 【POI2005】ska Piggy banks的相关文章

[POI2005]ska Piggy banks|并查集|tarjan

1529: [POI2005]ska Piggy banks Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 973  Solved: 445[Submit][Status][Discuss] Description Byteazar 有 N 个小猪存钱罐. 每个存钱罐只能用钥匙打开或者砸开. Byteazar 已经把每个存钱罐的钥匙放到了某些存钱罐里. Byteazar 现在想买一台汽车于是要把所有的钱都取出来. 他想尽量少的打破存钱罐取出所有的钱,

Bzoj1529/POI2005 ska Piggy banks

题目:ska Piggy banks 传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1529 题目描述:Byteazar 有 N 个小猪存钱罐. 每个存钱罐只能用钥匙打开或者砸开. Byteazar 已经把每个存钱罐的钥匙放到了某些存钱罐里. Byteazar 现在想买一台汽车于是要把所有的钱都取出来. 他想尽量少的打破存钱罐取出所有的钱,问最少要打破多少个存钱罐. 分析: (1)算法一:如果存钱罐i有存钱罐j的钥匙,就建一条(i->j)

【BZOJ】1529 [POI2005]ska Piggy banks

[算法](强连通分量)并查集 [题解] 1.用tarjan计算强连通分量并缩点,在新图中找入度为0的点的个数就是答案. 但是,会爆内存(题目内存限制64MB). 2.用并查集,最后从1到n统计fa[i]==i的数量即是答案. (tarjan) #include<cstdio> #include<algorithm> using namespace std; const int maxn=1000010; struct edge{int u,v,from;}e[maxn]; int

【BZOJ 2754 喵星球上的点名】

Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 2512  Solved: 1092[Submit][Status][Discuss] Description a180285幸运地被选做了地球到喵星球的留学生.他发现喵星人在上课前的点名现象非常有趣.   假设课堂上有N个喵星人,每个喵星人的名字由姓和名构成.喵星球上的老师会选择M个串来点名,每次读出一个串的时候,如果这个串是一个喵星人的姓或名的子串,那么这个喵星人就必须答到. 然而,由于喵星人的字

BZOJ 1529 [POI2005]ska Piggy banks(并查集)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1529 [题目大意] 给出一张n个点n条边的有向图,问选取几个点为起点可以遍历全图 [题解] 由于是n条边,因此图为基环森林,选取环上点一定可以到达连通块内所有点, 因此只要统计连通块个数即可. [代码] #include <cstdio> #include <algorithm> using namespace std; const int N=1000100; int

BZOJ 1529: [POI2005]ska Piggy banks [并查集]

题意: Byteazar 有 N 个小猪存钱罐. 每个存钱罐只能用钥匙打开或者砸开. Byteazar 已经把每个存钱罐的钥匙放到了某些存钱罐里. Byteazar 现在想买一台汽车于是要把所有的钱都取出来. 他想尽量少的打破存钱罐取出所有的钱,问最少要打破多少个存钱罐. 每个存钱罐只有一把钥匙... 和那道洛谷3月月赛R1T3长的一样的有向连通环套树... 任意连通分量环上一个点都可以到达全部点 #include <iostream> #include <cstdio> #inc

BZOJ 1529 ska piggy banks

1 #include <cstdio> 2 #include <algorithm> 3 #include <cstring> 4   5 #define up(a,b,c) for(register int c=a;c<=b;c++) 6   7 int n,fa[1000005],x,tot; 8   9 inline int Read(){ 10     int x = 0,f = 1; 11     char ch = getchar(); 12     

【BZOJ 2820】 YY的GCD

2820: YY的GCD Time Limit: 10 Sec  Memory Limit: 512 MB Submit: 807  Solved: 404 [Submit][Status] Description 神犇YY虐完数论后给傻×kAc出了一题 给定N, M,求1<=x<=N, 1<=y<=M且gcd(x, y)为质数的(x, y)有多少对 kAc这种傻×必然不会了,于是向你来请教-- 多组输入 Input 第一行一个整数T 表述数据组数 接下来T行,每行两个正整数,表示

【BZOJ】3319: 黑白树

http://www.lydsy.com/JudgeOnline/problem.php?id=3319 题意:给一棵n节点的树(n<=1e6),m个操作(m<=1e6),每次操作有两种:1.查询u到根的第一条黑边的编号.2.将u到v的路径全部染成黑色 #include <cstdio> #include <cstring> #include <cmath> #include <string> #include <iostream>