[loj3525]喷泉公园
作者:互联网
先将整张图$x$和$y$都缩小一半,即"道路"长度变为1,"长椅"变为放在格子中心
如果在没有长椅的限制下也无解(直接dfs即可判定),显然原问题也无解
否则,将所有格子(注意不是点)黑白染色,并强制横向道路(即从$(x,y)$到$(x+1,y)$的道路,纵向同理)对应的长椅在黑色格子的中心、纵向道路对应的长椅在白色格子的中心
在这个限制(构造)下,长椅的限制即变为黑(白)色格子的上下(左右)两边不同时为横(纵)向道路
从上到下、从左到右依次贪心选边(能选即选),简单画图不难发现合法
为了方便,可以使用map维护,复杂度为$o(n\log n)$
1 #include<bits/stdc++.h> 2 #include"parks.h" 3 using namespace std; 4 #define N 200005 5 #define vi vector<int> 6 #define pii pair<int,int> 7 #define mp make_pair 8 #define fi first 9 #define se second 10 int n,id[N],f[N]; 11 pii a[N]; 12 vi ansu,ansv,ansa,ansb; 13 map<int,int>mat[N],vis[N]; 14 bool cmp(int x,int y){ 15 return a[x]<a[y]; 16 } 17 int find(int k){ 18 if (k==f[k])return k; 19 return f[k]=find(f[k]); 20 } 21 void add(int x,int y,pii z){ 22 vis[z.fi][z.se]=1; 23 f[find(x)]=find(y); 24 ansu.push_back(x-1); 25 ansv.push_back(y-1); 26 ansa.push_back(z.fi*2+1); 27 ansb.push_back(z.se*2+1); 28 } 29 int construct_roads(vi x,vi y){ 30 n=x.size(); 31 for(int i=1;i<=n;i++){ 32 a[i]=mp(x[i-1]/2,y[i-1]/2); 33 id[i]=f[i]=mat[a[i].fi][a[i].se]=i; 34 } 35 sort(id+1,id+n+1,cmp); 36 for(int j=1;j<=n;j++){ 37 int i=id[j],k=mat[a[i].fi+1][a[i].se]; 38 if ((k)&&(find(i)!=find(k))){ 39 if ((a[i].fi+a[i].se)&1)add(i,k,a[i]); 40 else{ 41 if (!vis[a[i].fi][a[i].se-1])add(i,k,mp(a[i].fi,a[i].se-1)); 42 } 43 } 44 k=mat[a[i].fi][a[i].se+1]; 45 if ((k)&&(find(i)!=find(k))){ 46 if ((a[i].fi+a[i].se)%2==0)add(i,k,a[i]); 47 else{ 48 if (!vis[a[i].fi-1][a[i].se])add(i,k,mp(a[i].fi-1,a[i].se)); 49 } 50 } 51 } 52 for(int i=1;i<=n;i++) 53 if (find(i)!=find(1))return 0; 54 build(ansu,ansv,ansa,ansb); 55 return 1; 56 }View Code
标签:loj3525,格子,int,公园,喷泉,道路,长椅,include,define 来源: https://www.cnblogs.com/PYWBKTDA/p/15063484.html