【DP】ants

来源:互联网 发布:明星拼图软件 编辑:程序博客网 时间:2024/05/20 22:36

题目简述: 

平面上有N只蚂蚁,每个蚂蚁的位置我们用一个整数坐标(x,y)表示。现在我们想知道这个平面上可能有几群蚂蚁。我们称一些蚂蚁组成一个群,当且仅当:这个群里任意两只蚂蚁之间的距离,都严格小于这个群里任意一只蚂蚁到不属于这个群的任意一只蚂蚁之间的距离。两只蚂蚁之间的距离为sqrt((x1-x2)^2+(y1-y2)^2)。对重合蚂蚁的特别声明:一只蚂蚁始终可以作为一个群,即可以认为自己到自己距离为-oo,若有4只重合蚂蚁,则答案为1001。


我们思考: 如果按照边权加入边, 若某一时刻若有一个连通块是一个完全图, 那么这个块是可以组成一个群的。

一个思路: 记录当前群数 Gr, 我们不断加边进去(相同的边必须一起加进去), 不断减小Gr, 当某一个时刻这个图是稳定的(每个连通块单独成群) 那么ans[Gr]= 1。

显然这是不行的。

但我们考虑, 如果一个群 G 是由 G1 + G2 组成的, 群F 是由 F1 + F2 组成的(F1 , F2, G1, G2都是可以单独成群) , 那么 群数有可能为 2, 3, 4.

若G1 - G2,   F1  - F2同时合并, 如果按照上面的思路, Gr将直接-2, 所以 3 这种情况将直接忽略。


所以对于一个连通块, 我们记录一个数组, 表示这个群可以由几个群构成的。

每次合并, 只要合并背包就行了。


Pro:

#include<cstdio>#include<cstring>#include<set>#include<string>#include<algorithm>#include<ctime>#define sett set<int>::iteratorusing namespace std;struct pa{int x,y,l;} p[5010],dis[1000010];bool ans[5010];int n,fa[5010],tot,size[5010],maxl[5010],nn[1000010],num;set<int> can[5010],node[5010];bool cmp(pa a,pa b) {return a.l<b.l;}int sqr(int x) {return x*x;}int getfa(int x){if (fa[x]!=x) fa[x]=getfa(fa[x]); return fa[x];}void update(int &a,int b){if (b>a) a=b;}int Dis(int i,int j){return sqr(p[i].x-p[j].x)+sqr(p[i].y-p[j].y);}int main(){freopen("ant.in","r",stdin); freopen("ant.out","w",stdout);for (scanf("%d",&n);n;scanf("%d",&n)){for (int i=0;i<n;i++)         {            scanf("%d%d",&p[i].x,&p[i].y);can[i].clear(),can[i].insert(0);fa[i]=i,size[i]=1; maxl[i]=0;node[i].clear(); node[i].insert(i);}tot=0;for (int i=0;i<n;i++)for (int j=0;j<n;j++) if (i!=j) dis[tot].x=i,dis[tot].y=j,dis[tot++].l=Dis(i,j);sort(dis,dis+tot,cmp);for (int i=0;i<tot;){int j=i;num=0;for (;j<tot && dis[j].l==dis[i].l;j++){int f1=getfa(dis[j].x),f2=getfa(dis[j].y);if (f1!=f2){set<int> now; now.clear();for (sett ii=can[f1].begin();ii!=can[f1].end();ii++)for (sett jj=can[f2].begin();jj!=can[f2].end();jj++)now.insert((*ii)+(*jj));for (sett ii=now.begin();ii!=now.end();ii++) can[f1].insert(*ii);now.clear();update(maxl[f1],maxl[f2]);for (sett ii=node[f1].begin();ii!=node[f1].end();ii++)for (sett jj=node[f2].begin();jj!=node[f2].end();jj++)update(maxl[f1],Dis(*ii,*jj));for (sett jj=node[f2].begin();jj!=node[f2].end();jj++) node[f1].insert(*jj);fa[f2]=f1; size[f1]+=size[f2];}nn[num++]=f1;}for (int k=0;k<num;k++)if (fa[nn[k]]==nn[k] && maxl[nn[k]]<=dis[i].l) can[nn[k]].insert(size[nn[k]]-1);i=j;}memset(ans,0,sizeof ans);for (int i=0;i<n;i++) if (size[i]==n) for (sett j=can[i].begin();j!=can[i].end();j++) ans[n-(*j)]=true;for (int i=1;i<=n;i++) if (ans[i]) printf("1");else printf("0");puts("");}return 0;}


原创粉丝点击