備戰noip week8

BILL666發表於2020-10-27

POJ1144 網路

description:

給出一張\(N\)個點的無向圖,求其中割點的個數

data range:

\(N\le 100\)

solution:

一道模板題(但是讀入實在是把我噁心壞了)

#include<cstdio>
#include<vector>
#include<algorithm>
#include<iostream>
#include<sstream>
using namespace std;
const int N=105;
int n,dfn[N],low[N],sign;
vector<int>e[N];
bool flag[N];
string s;
void dfs(int u,int fa)
{
	low[u]=dfn[u]=++sign;
	int cd=0;
	for(int i=0;i<e[u].size();++i)
	{
		int v=e[u][i],&lu=low[u];
		if(v==fa)continue;
		if(!dfn[v])
		{
			dfs(v,u);lu=min(lu,low[v]);
			if(low[v]>=dfn[u]&&u!=fa)flag[u]=1;
			if(u==fa)++cd;
		}
		else lu=min(lu,dfn[v]);
	}
	if(u==fa&&cd>1)flag[u]=1;
}
int main()
{
	while(1)
	{
		cin>>n;if(!n)break;
		for(int i=1;i<=n;++i)e[i].clear();
		while(1)
		{
			int u;cin>>u;if(!u)break;
			getline(cin,s);stringstream ss(s);
			int v;
			while(ss>>v)
				e[u].push_back(v),e[v].push_back(u);
		}
		fill(flag+1,flag+n+1,0);
		fill(dfn+1,dfn+n+1,0);
		fill(low+1,low+n+1,0);sign=0;
		for(int i=1;i<=n;++i)if(!dfn[i])dfs(i,i);
		printf("%d\n",count(flag+1,flag+n+1,1));
	}
	return 0;
}

POJ2117 Electricity

description:

給定一張\(N\)個點的無向圖,詢問刪除一個點後最多有多少個聯通分量

data range:

\(N\le 10^4\)

solution:

還是比較模板
求割點時順便統計下就行了
但要稍微注意下圖不連通的情況

#include<cstdio>
#include<vector>
using namespace std;
const int N=1e4+5;
int n,m,low[N],dfn[N],sign,ans;
vector<int>e[N];
void dfs(int u,int fa)
{
	low[u]=dfn[u]=++sign;
	int cd=u==fa?0:1;
	for(int i=0;i<e[u].size();++i)
	{
		int v=e[u][i],&lu=low[u];
		if(v==fa)continue;
		if(!dfn[v])
		{
			dfs(v,u),lu=min(lu,low[v]);
			if(u!=fa&&low[v]>=dfn[u])++cd;
			else if(u==fa)++cd;
		}
		else lu=min(lu,dfn[v]);
	}
	ans=max(ans,cd);
}
int main()
{
	while(scanf("%d%d",&n,&m)==2)
	{
		if(!n&&!m)break;
		for(int i=1;i<=n;++i)e[i].clear();
		for(int i=1;i<=m;++i)
		{
			int u,v;scanf("%d%d",&u,&v);++u,++v;
			e[u].push_back(v),e[v].push_back(u);
		}
		int cnt=0;sign=0,ans=0;
		fill(dfn+1,dfn+n+1,0);
		for(int i=1;i<=n;++i)
			if(!dfn[i])++cnt,dfs(i,i);
		printf("%d\n",ans+cnt-1);
	}
	return 0;
}

HDU3749 Financial Crisis

description:

給出一個\(N\)個點的無向圖,有\(Q\)次詢問,每次詢問給出兩個點\(u,v\),如果它們間沒有路徑,輸出\(zero\);否則如果它們間有至少兩條點不重複的路徑,輸出\(two\ or\ more\);否則輸出\(one\)

data range:

\(N\le 5*10^3\)
\(Q\le 10^3\)

solution:

首先如果兩個點不連通,那麼輸出\(zero\),這個可以用並查集來維護
注意到點不重複這四個字
那麼如果有至少兩條點不重複的路徑,那麼這兩個點一定是在同一個點雙聯通分量內的
其他情況都輸出\(one\)
p.s.這道題可以當做點雙的一個完整模板

code:

#include<cstdio>
#include<vector>
#include<stack>
#include<algorithm>
using namespace std;
const int N=5005;
int n,m,q,fa[N],dfn[N],low[N],sign,cnt,id[N],kase;
struct edge{int u,v;edge(int _u=0,int _v=0){u=_u,v=_v;}};
stack<edge>s;
vector<int>e[N],bcc[N],bccs[N];
int fd(int x){return fa[x]==x?x:fa[x]=fd(fa[x]);}
inline void merge(int u,int v){u=fd(u),v=fd(v);if(u!=v)fa[u]=v;}
inline void add(int u,int t)
{
	if(id[u]==t)return;
	id[u]=t;bcc[t].push_back(u),bccs[u].push_back(t);
}
void dfs(int u,int fa)
{
	low[u]=dfn[u]=++sign;
	for(int i=0;i<e[u].size();++i)
	{
		int v=e[u][i],&lu=low[u];
		edge eg=edge(u,v);
		if(v==fa)continue;
		if(!dfn[v])
		{
			s.push(eg);
			dfs(v,u),lu=min(lu,low[v]);
			if(low[v]>=dfn[u])
			{
				++cnt;
				while(1)
				{
					edge x=s.top();s.pop();
					add(x.u,cnt),add(x.v,cnt);
					if(x.u==u&&x.v==v)break;
				}
			}
		}
		else if(dfn[v]<dfn[u])
			s.push(eg),lu=min(lu,dfn[v]);
	}
}
inline int solve(int u,int v)
{
	if(fd(u)!=fd(v))return 0;
	vector<int>&bu=bccs[u],&bv=bccs[v];
	for(int i=0;i<bu.size();++i)
		for(int j=0;j<bv.size();++j)
			if(bu[i]==bv[j]&&bcc[bu[i]].size()>2)return 2;
	return 1;
}
int main()
{
	while(scanf("%d%d%d",&n,&m,&q)==3)
	{
		if(!n&&!m&&!q)break;
		for(int i=1;i<=n;++i)
			e[i].clear(),bcc[i].clear(),bccs[i].clear(),fa[i]=i;
		for(int i=1;i<=m;++i)
		{
			int u,v;scanf("%d%d",&u,&v);++u,++v;
			e[u].push_back(v),e[v].push_back(u);
			merge(u,v);
		}
		fill(dfn+1,dfn+n+1,0);sign=0;cnt=0;
		fill(id+1,id+n+1,0);
		for(int i=1;i<=n;++i)if(!dfn[i])dfs(i,i);
		printf("Case %d:\n",++kase);
		while(q--)
		{
			int u,v;scanf("%d%d",&u,&v);u++,v++;
			int ans=solve(u,v);
			puts(ans?(ans==1?"one":"two or more"):"zero");
		}
	}
	return 0;
}

HDU4587 TWO NODES

description:

給出一個\(N\)個點的無向圖,詢問刪去其中兩個點後最多可以將其分成多少個聯通塊

data range:

\(N\le 5*10^3\)

solution:

考慮到資料範圍\(N\le 5000\)
因此我們可以先列舉其中一個被刪除的點
然後在剩餘的圖上計算刪去當前點後形成的聯通塊個數即可
還是注意下圖不連通的情況

code:

#include<vector>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=5005;
int n,m,cut,dfn[N],low[N],sign,ans,anss;
vector<int>e[N];
void dfs(int u,int fa)
{
    low[u]=dfn[u]=++sign;
    int cd=u==fa?0:1;
    for(int i=0;i<e[u].size();++i)
    {
        int v=e[u][i],&lu=low[u];
        if(v==fa||v==cut)continue;
        if(!dfn[v])
        {
            dfs(v,u),lu=min(lu,low[v]);
            if(low[v]>=dfn[u]&&u!=fa)++cd;
            else if(u==fa)++cd;
        }
        else if(dfn[v]<dfn[u])lu=min(lu,dfn[v]);
    }
    ans=max(ans,cd);
}
int main()
{
    while(scanf("%d%d",&n,&m)==2)
    {
        for(int i=1;i<=n;++i)e[i].clear();
        for(int i=1;i<=m;++i)
        {
            int u,v;scanf("%d%d",&u,&v);++u,++v;
            e[u].push_back(v),e[v].push_back(u);
        }
        anss=0;
        for(int i=1;i<=n;++i)
        {
            cut=i;sign=0;int cnt=0;ans=0;
            fill(dfn+1,dfn+n+1,0);
            for(int j=1;j<=n;++j)
                if(j!=cut&&!dfn[j])++cnt,dfs(j,j);
            anss=max(anss,ans+cnt-1);
        }
        printf("%d\n",anss);
    }
    return 0;
}

POJ3177 分離的路徑(USACO 2006 Jan. Gold)

description:

給出一個\(N\)個點\(M\)條邊的無向圖,詢問至少新新增多少點後可以使得原圖邊雙聯通

data range:

\(N\le 5000\)
\(M\le 10^4\)

solution:

我們可以將原圖的所有極大邊雙連通分量縮點
然後參考有向圖新增儘量少的邊使得整個圖為強聯通的做法
我們只要將縮點後所有度數為1的點兩個一組地用一條邊相連即可
形式化地,設度數為1的點有\(x\)個,那麼就需要新增\(\lceil \frac{x}{2}\rceil\)條邊
具體做法其實沒有說的那麼麻煩
直接在原圖上找到左右的橋
然後再dfs一遍,強制不能經過橋,這樣就可以找到所有的邊雙了
最後列舉每條邊統計度數即可

#include<bits/stdc++.h>
using namespace std;
const int N=5005,M=2e4+5;
int n,m,tot=1,sign,cnt;
int fi[N],ne[M],to[M],dfn[N],low[N],id[N],deg[N];
bool flag[M];
inline void add(int x,int y){ne[++tot]=fi[x],fi[x]=tot,to[tot]=y;}
void dfs(int u,int fa)
{
	low[u]=dfn[u]=++sign;
	for(int i=fi[u];i;i=ne[i])
	{
		int v=to[i],&lu=low[u];
		if(v==fa)continue;
		if(!dfn[v])
		{
			dfs(v,u),lu=min(lu,low[v]);
			if(low[v]>dfn[u])flag[i]=flag[i^1]=1;
		}
		else if(dfn[v]<dfn[u])lu=min(lu,dfn[v]);
	}
}
void _dfs(int u,int col)
{
	id[u]=col;
	for(int i=fi[u];i;i=ne[i])
	{
		int v=to[i];
		if(flag[i]||id[v])continue;
		_dfs(v,col);
	}
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;++i)
	{
		int u,v;scanf("%d%d",&u,&v);
		add(u,v),add(v,u);
	}
	for(int i=1;i<=n;++i)if(!dfn[i])dfs(i,i);
	for(int i=1;i<=n;++i)if(!id[i])_dfs(i,++cnt);
	for(int i=1;i<=n;++i)
		for(int j=fi[i];j;j=ne[j])
			if(id[i]!=id[to[j]])++deg[id[i]],++deg[id[to[j]]];
	int ans=count(deg+1,deg+cnt+1,2);
	printf("%d\n",ans+1>>1);
	return 0;
}

POJ3352 Road Construction
同上一道題
井下礦工 (Mining Your Own Business, WF2011, LA5135)

description:

在一個無向圖上選擇儘量少的點塗黑,使得刪除任意一個點後,每個連通分量裡都至少有一個黑點。

data range:

\(N\le 5*10^4\)

solution:

先求出所有的極大點雙連通分量
對於每個點雙連通分量單獨考慮,設其大小為\(sz\)
如果其內部割點個數\(>1\),那麼不用在其內部塗黑(因為如果某個割點被刪去後,還可以通過其他割點和別的聯通分量形成聯通塊)
如果其內部割點個數\(=1\),那麼需要在一個不是割點的位置塗黑,方案數就是\(sz-1\)(即去除割點)
如果其內部割點個數\(=0\),那麼就需要在其中任選兩個塗黑,方案數就是\(sz*(sz-1)/2\)(沒有割點就相當於這個塊是獨立的,泡不到其他塊,因此要選兩個點)
另外還是要注意圖不連通的情況

code:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5e5+5;
int n,m,sign,cnt,low[N],dfn[N],id[N],fa[N],sz[N];
bool flag[N],pd[N];
vector<int>e[N],bcc[N];
int fd(int x){return fa[x]==x?x:fa[x]=fd(fa[x]);}
inline bool isnum(char &ch){return '0'<=ch&&ch<='9';}
inline int read()
{
	int s=0,w=1; char ch=getchar();
	for(;!isnum(ch);ch=getchar())if(ch=='-')w=-1;
	for(;isnum(ch);ch=getchar())s=(s<<1)+(s<<3)+(ch^48);
	return s*w;
}
inline void add(int u,int v)
{
	if(id[u]==v)return;
	id[u]=v,bcc[v].push_back(u);
}
int stx[N],sty[N],top;
void dfs(int u,int pr)
{
	low[u]=dfn[u]=++sign;
	int cd=0;
	for(int i=0;i<e[u].size();++i)
	{
		int v=e[u][i];
		if(v==pr)continue;
		if(!dfn[v])
		{	
			++cd;stx[++top]=u,sty[top]=v;
			dfs(v,u),low[u]=min(low[u],low[v]);
			if(low[v]>=dfn[u])
			{
				++cnt;flag[u]=1;
				while(1)
				{
					add(stx[top],cnt),add(sty[top],cnt);
					if(stx[top]==u&&sty[top]==v)break;--top;
				}
				--top;
			}
		}
		else if(dfn[v]<dfn[u])
		{
			stx[++top]=u,sty[top]=v;
			low[u]=min(low[u],dfn[v]);
		}
	}
	if(u==pr&&cd<=1)flag[u]=0;
}
int main()
{
	for(int kase=1;;++kase)
	{
		m=read();if(!m)break;n=0;
		for(int i=1;i<=m+1;++i)fa[i]=i,sz[i]=1;
		for(int i=1;i<=m;++i)
		{
			int u=read(),v=read();n=max(n,max(u,v));
			e[u].push_back(v),e[v].push_back(u);
			u=fd(u),v=fd(v);
			if(u!=v)fa[u]=v,sz[v]+=sz[u];
		}
		for(int i=1;i<=n;++i)if(!dfn[i])dfs(i,i);
		int ans1=0;ll ans2=1ll;
		for(int i=1;i<=cnt;++i)
		{
			int num=0;
			for(int j=0;j<bcc[i].size();++j)num+=flag[bcc[i][j]];
			if(num==1)++ans1,ans2*=bcc[i].size()-1,pd[fd(bcc[i][0])]=1;
		}
		for(int i=1;i<=n;++i)
			if(i==fd(i)&&!pd[i])
				pd[i]=1,ans1+=min(sz[i],2),ans2*=sz[i]>1?1ll*sz[i]*(sz[i]-1)/2ll:1;
		printf("Case %d: %d %lld\n",kase,ans1,ans2);
		for(int i=1;i<=n;++i)e[i].clear(),bcc[i].clear();
		top=cnt=sign=0;fill(dfn+1,dfn+n+1,0);
		fill(id+1,id+n+1,0);fill(flag+1,flag+n+1,0);
		fill(pd+1,pd+n+1,0);
	}
	return 0;
}

HDU 3394 Railway

description:

給一個\(N\)個點的無向圖,如果至少有兩個環共用了一些邊,那麼這些邊被認為是衝突邊,如果一些邊不在任何一個環中,這些邊被認為是多餘邊,問這個圖中有多少多餘邊和衝突邊

data range:

\(N\le 10^4\)

solution:

對於多餘邊,直接在原圖上找橋就可以了
以下考慮統計衝突邊
對於每一個點雙聯通分量,不妨設其中點的個數為\(cntp\),邊的個數為\(cnte\)
容易知道\(cntp\le cnte\)
如果\(cntp==cnte\)那麼會恰好形成一個簡單環

但如果\(cntp<cnte\),那麼這個聯通分量中所有邊都是衝突邊

上圖是\(cntp=cnte-1\)的情況,容易發現其中已經有3個環
然後就是模板了

code:

#include<cstdio>
#include<algorithm>
using namespace std;
const int N=10005,M=1e5+5;
int n,m,tot=1,sign,ans1,ans2,cnt;
int fi[N],ne[M<<1],to[M<<1];
int dfn[N],low[N],vis[N];
bool flag[M<<1];
inline bool isnum(char &ch){return '0'<=ch&ch<='9';}
inline int read()
{
    int s=0,w=1; char ch=getchar();
    for(;!isnum(ch);ch=getchar())if(ch=='-')w=-1;
    for(;isnum(ch);ch=getchar())s=(s<<1)+(s<<3)+(ch^48);
    return s*w;
}
inline void add(int x,int y){ne[++tot]=fi[x],fi[x]=tot,to[tot]=y;}
int stx[M],sty[M],top;
void dfs(int u,int fa)
{
    low[u]=dfn[u]=++sign;
    for(int i=fi[u];i;i=ne[i])
    {
        int v=to[i];
        if(v==fa)continue;
        if(!dfn[v])
        {
            stx[++top]=u,sty[top]=v;
            dfs(v,u),low[u]=min(low[u],low[v]);
            if(low[v]>=dfn[u])
            {
                int cnte=0,cntp=0;
                ++cnt;if(low[v]>dfn[u])++ans1;
                for(;;)
                {
                    int x=stx[top],y=sty[top];--top;++cnte;
                    if(vis[x]!=cnt)vis[x]=cnt,++cntp;
                    if(vis[y]!=cnt)vis[y]=cnt,++cntp;
                    if(x==u&&y==v)break;
                }
                if(cnte>cntp)ans2+=cnte;
            }
        }
        else if(dfn[v]<dfn[u])
        {
            low[u]=min(low[u],dfn[v]);
            stx[++top]=u,sty[top]=v;
        }
    }
}
int main()
{
    while(1)
    {
        n=read(),m=read();if(!n&&!m)break;
        fill(fi+1,fi+n+1,0);tot=1;
        for(int i=1;i<=m;++i)
        {
            int u=read(),v=read();++u,++v;
            add(u,v),add(v,u);
        }
        fill(flag+1,flag+tot+1,0);cnt=0;
        fill(dfn+1,dfn+n+1,0);sign=0;ans1=ans2=0;
        fill(vis+1,vis+n+1,0);
        for(int i=1;i<=n;++i)if(!dfn[i])dfs(i,i);
        printf("%d %d\n",ans1,ans2);
    }
    return 0;
}

SPOJ - STC10. Blockade, POI 2008

description:

Byteotia 城市有\(n\)個城鎮,\(m\)條雙向道路。每條道路連線兩個不同的城鎮,沒有重複的道路,所有城鎮連通。輸出\(n\)個數,代表如果把與第\(i\)個點連線的所有邊去掉,將有多少對點不能互通。

data range:

\(N\le 10^5\)

solution:

對於每個點,刪去後至少有\(2*(n-1)\)個點對不連通(即其他點無法到達這個已經刪去的點)
對於割點,可以方便地處理出刪去後每個聯通塊的大小(即\(dfs\)樹上的子樹大小)
然後再加上聯通塊兩兩相乘之和的貢獻就是這個點的答案了
對於非割點,則沒有額外的貢獻

code:

#include<bits/stdc++.h>
#define pb push_back
using namespace std;
const int N=1e5+5;
typedef long long ll;
int n,m,sign,dfn[N],low[N];
vector<int>e[N];
ll ans[N];
inline bool isnum(char &ch){return '0'<=ch&&ch<='9';}
inline int read()
{
	int s=0,w=1; char ch=getchar();
	for(;!isnum(ch);ch=getchar())if(ch=='-')w=-1;
	for(;isnum(ch);ch=getchar())s=(s<<1)+(s<<3)+(ch^48);
	return s*w;
}
inline ll work(vector<int>&p)
{
	ll anss=0,sm=0;
	for(int i=0;i<p.size();++i)
		anss+=sm*p[i],sm+=1ll*p[i];
	return anss;
}
int dfs(int u,int fa)
{
	low[u]=dfn[u]=++sign;
	int sz=1,cd=0,now=0;vector<int>p;
	for(int i=0;i<e[u].size();++i)
	{
		int v=e[u][i];
		if(v==fa)continue;
		if(!dfn[v])
		{
			++cd;int vsz=dfs(v,u);
			low[u]=min(low[u],low[v]),sz+=vsz;
			if(low[v]>=dfn[u])p.pb(vsz),now+=vsz;
		}
		else low[u]=min(low[u],dfn[v]);
	}
	if(u==fa&&cd<=1)p.clear();
	if(u!=fa)p.pb(n-now-1);
	ans[u]+=work(p);//p中數的兩兩相乘之和
	return sz;
}
int main()
{
	n=read(),m=read();
	for(int i=1;i<=m;++i)
	{
		int u=read(),v=read();
		e[u].pb(v),e[v].pb(u);
	}
	for(int i=1;i<=n;++i)ans[i]=1ll*(n-1);
	for(int i=1;i<=n;++i)if(!dfn[i])dfs(i,i);
	for(int i=1;i<=n;++i)printf("%lld\n",ans[i]<<1);
	return 0;
}

圓桌騎士 (Knights of the Round Table,LA3523)

description:

給出一個\(N\)個點的無向圖,求出其中有多少個點滿足它們不在任何一個長度為奇數的簡單環上

data range:

\(N\le 10^3\)

solution:

首先對於一個奇環,它一定位於一個點雙聯通分量之中
於是對原圖處理出所有點雙
單獨考慮一個點雙,如果其中不存在奇環(即是一個二分圖),那麼其中的點都是滿足條件的
否則,對於奇環上的點一定不滿足,那對於奇環以外的點呢?

首先由於連通性,因此存在一條路徑從v到u1
又由於雙連通性,因此存在一條路徑從v到u2(兩條點不重複的路徑分別是v->u2和v->u1->u2)
那麼又由於這個環是一個奇環,所以v也一定位於一個奇環上(綠色的環或者紅色的環)
然後就可做了

code:

#include<bits/stdc++.h>
using namespace std;
const int N=1005;
int n,m,sign,cnt,dfn[N],low[N],id[N],col[N];
vector<int>bcc[N],e[N];
bool G[N][N],pd[N],flag[N];
int stx[N*N],sty[N*N],top;
inline void add(int u,int t)
{
	if(id[u]==t)return;
	id[u]=t,bcc[t].push_back(u);
}
void dfs(int u,int fa)
{
	low[u]=dfn[u]=++sign;
	int cd=0;
	for(int i=0;i<e[u].size();++i)
	{
		int v=e[u][i];
		if(v==fa)continue;
		if(!dfn[v])
		{
			++cd;stx[++top]=u,sty[top]=v;
			dfs(v,u),low[u]=min(low[u],low[v]);
			if(low[v]>=dfn[u])
			{
				++cnt;
				for(;;)
				{
					int x=stx[top],y=sty[top];--top;
					add(x,cnt),add(y,cnt);
					if(x==u&&y==v)break;
				}
			}
		}
		else if(dfn[v]<dfn[u])
		{
			stx[++top]=u,sty[top]=v;
			low[u]=min(low[u],dfn[v]);
		}
	}
}
bool bwpd(int u,int c)
{
	if(col[u]>=0)return col[u]==c;
	col[u]=c;bool o=1;
	for(int i=0;i<e[u].size();++i)
	{
		int v=e[u][i];
		if(!flag[v])continue;
		o&=bwpd(v,c^1);
	}
	return o;
}
int main()
{
	while(scanf("%d%d",&n,&m)==2&&n&&m)
	{
		for(int i=1;i<=n;++i)
			for(int j=1;j<=n;++j)
				if(i!=j)G[i][j]=1;
		while(m--)
		{
			int u,v;scanf("%d%d",&u,&v);
			G[u][v]=G[v][u]=0;
		}
		for(int i=1;i<=n;++i)e[i].clear();
		for(int i=1;i<=n;++i)
			for(int j=1;j<=n;++j)
				if(G[i][j])e[i].push_back(j);
		for(int i=1;i<=n;++i)bcc[i].clear();
		fill(dfn+1,dfn+n+1,0);top=sign=cnt=0;
		fill(id+1,id+n+1,0);fill(flag+1,flag+n+1,0);
		for(int i=1;i<=n;++i)if(!dfn[i])dfs(i,i);
		fill(col+1,col+n+1,-1);fill(pd+1,pd+n+1,0);
		for(int i=1;i<=cnt;++i)
		{
			for(int j=0;j<bcc[i].size();++j)flag[bcc[i][j]]=1;
			if(!bwpd(bcc[i][0],1))
				for(int j=0;j<bcc[i].size();++j)pd[bcc[i][j]]=1;
			for(int j=0;j<bcc[i].size();++j)flag[bcc[i][j]]=0,col[bcc[i][j]]=-1;
		}
		printf("%d\n",count(pd+1,pd+n+1,0));
	}
	return 0;
}