NCPC 2016 A Artwork(并查集)
来源:互联网 发布:pc网络电视直播软件 编辑:程序博客网 时间:2024/05/16 15:01
链接Artwork
- 题目大意
给你一个n*m的格子,依次向其中放入q个线段,让你输出每放一个线段之后图中的连通分量有多少个
分析
逆向思维
先将所有线段放上去之后从最后一个依次取,每取一个用并查集维护连通分量的个数代码
#include<cstdio>#include<iostream>#include<cmath>#include<cstring>#include<cstdlib>#include<queue>#include<map>#include<algorithm>#include<set>#include<stack>using namespace std;#define LL long long intconst int MAXN=1005;int n,m,q;//n行m列int ans[10005];//ans[i]保存第i次查询的结果int cnt;int grid[MAXN][MAXN];int belong[MAXN][MAXN];//belong[x][y]表示格子(x,y)属于哪一个连通分量bool bj[MAXN][MAXN];//bj[i][j]表示格子(i,j)是否被访问过int belong_cnt;int pa[MAXN*MAXN];//fa[i]表示格子i所属的类别int Rank[MAXN*MAXN];struct Line{ int X1,Y1,X2,Y2; Line(){} Line(int x1,int z1,int x2,int z2) {X1=x1,Y1=z1,X2=x2,Y2=z2;}}line[10005];int line_cnt;void Init(){ cnt=0; line_cnt=0; belong_cnt=0; memset(grid,0,sizeof(grid));}void In(){ int X1,Y1,X2,Y2; for(int i=1;i<=q;i++) { scanf("%d%d%d%d",&Y1,&X1,&Y2,&X2);//坐标系进行了一次变换 line[++line_cnt]=Line(X1,Y1,X2,Y2); }}void Cover(int X1,int Y1,int X2,int Y2)//用线段覆盖grid{ int min_x=min(X1,X2);int max_x=max(X1,X2); int min_y=min(Y1,Y2);int max_y=max(Y1,Y2); if(X1==X2)for(int j=min_y;j<=max_y;j++)grid[X1][j]++; else if(Y1==Y2) for(int i=min_x;i<=max_x;i++)grid[i][Y1]++;}void Print_grid(){ cout<<endl; for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { cout<<grid[i][j]<<" "; } cout<<endl; }}int Find(int x){ return pa[x]==x ? x : x=Find(pa[x]);}void Union(int a,int b){ int xa=Find(a); int xb=Find(b); if(Rank[xa]>Rank[xb]){pa[xb]=xa;}//Rank优化,Rank表示树的深度 else { pa[xa]=xb; if(Rank[xa]==Rank[xb])Rank[xb]++; }}void Print_belong(){ cout<<endl; for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { cout<<Find(belong[i][j])<<" "; } cout<<endl; }}bool Is_out(int x,int y){ if(x<1 || x>n || y<1 || y>m)return 1; else return 0;}void dfs(int x,int y){ if(bj[x][y]==1 || grid[x][y]>0)return ; belong[x][y]=belong_cnt; bj[x][y]=1; if(!Is_out(x-1,y))dfs(x-1,y); if(!Is_out(x,y-1))dfs(x,y-1); if(!Is_out(x+1,y))dfs(x+1,y); if(!Is_out(x,y+1))dfs(x,y+1);}void Init_Work()//初始化每个格子属于哪一个连通分量{ for(int i=1;i<=line_cnt;i++) { Cover(line[i].X1,line[i].Y1,line[i].X2,line[i].Y2);//用线段覆盖grid } //Print_grid(); memset(bj,0,sizeof(bj)); for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { if(bj[i][j]==0 && grid[i][j]==0) { belong[i][j]=(++belong_cnt);//新的一个连通分量 pa[belong_cnt]=belong_cnt;//初始化类别的父亲是自己 Rank[belong_cnt]=1; dfs(i,j); } } }}void Classify(int x,int y,int &classes)//对一个新的格子进行分类,cnt表示合并了几个类{ belong[x][y]=0;//(x,y)格子应该归的类别 if(!Is_out(x-1,y) && belong[x-1][y]!=0) { if(belong[x][y]==0)belong[x][y]=pa[belong[x-1][y]]; else if(Find(belong[x][y])!=Find(belong[x-1][y])){Union(belong[x][y],belong[x-1][y]);classes--;} } if(!Is_out(x,y-1) && belong[x][y-1]!=0) { if(belong[x][y]==0)belong[x][y]=pa[belong[x][y-1]]; else if(Find(belong[x][y])!=Find(belong[x][y-1])){Union(belong[x][y],belong[x][y-1]);classes--;} } if(!Is_out(x+1,y) && belong[x+1][y]!=0) { if(belong[x][y]==0)belong[x][y]=pa[belong[x+1][y]]; else if(Find(belong[x][y])!=Find(belong[x+1][y])){Union(belong[x][y],belong[x+1][y]);classes--;} } if(!Is_out(x,y+1) && belong[x][y+1]!=0) { if(belong[x][y]==0)belong[x][y]=pa[belong[x][y+1]]; else if(Find(belong[x][y])!=Find(belong[x][y+1])){Union(belong[x][y],belong[x][y+1]);classes--;} } if(belong[x][y]==0) { belong[x][y]=++belong_cnt; pa[belong_cnt]=belong_cnt; Rank[belong_cnt]=1; classes++; }}void Work(){ //Print_grid(); //Print_belong(); int classes=belong_cnt; for(int k=line_cnt;k>=1;k--) { ans[k]=classes; int X1=line[k].X1,Y1=line[k].Y1,X2=line[k].X2,Y2=line[k].Y2; int min_x=min(X1,X2);int max_x=max(X1,X2); int min_y=min(Y1,Y2);int max_y=max(Y1,Y2); if(X1==X2) { for(int j=min_y;j<=max_y;j++) { grid[X1][j]--; if(grid[X1][j]==0)Classify(X1,j,classes); } } else if(Y1==Y2) { for(int i=min_x;i<=max_x;i++) { grid[i][Y1]--; if(grid[i][Y1]==0)Classify(i,Y1,classes); } } } for(int i=1;i<=line_cnt;i++) { printf("%d\n",ans[i]); }}int main(){ while(scanf("%d%d%d",&m,&n,&q)!=EOF)//n行m列 { Init(); In(); Init_Work(); Work(); } return 0;}/*4 6 52 2 2 61 3 4 32 5 3 54 6 4 61 6 4 6*/
阅读全文
0 0
- NCPC 2016 A Artwork(并查集)
- 计蒜客 A.Artwork 并查集+set
- 并查集 Problem A
- Canada Cup 2016 A.Jumping Ball并查集 .
- 【并查集】Is it a tree?
- 【并查集】Is it A Tree?
- 并查集,贪心:Color A Tree
- A Bug's Life 并查集
- 并查集(A - Friendship)
- 并查集 A Bug's Life
- CodeForces 123A 并查集
- UVA1493 - Draw a Mess(并查集)
- Is It A Tree?(并查集)
- A Bug's Life 并查集
- A Bug's Life_poj2492_并查集
- 【codeforce】744A 并查集
- CodeForces - 744A (并查集)
- Is It A Tree? (并查集)
- 设计模式——代理模式
- pandas中ix loc iloc的区别
- qbxt Day3 DP+DP+贪心
- POJ 2762 单向的连通图
- 【nyoj712】探寻宝藏
- NCPC 2016 A Artwork(并查集)
- 挑选pick
- HDOJ2050
- Linux Shell编程入门
- eclispe中//TODO的用法
- 【XSY1285】【BZOJ3814】【清华集训2014】简单回路 状压DP
- Jzoj3899 逻辑的连通性
- Spring黑马笔记入门二
- HDU-5046 Airport(二分+DLX重复覆盖)