UOJ220 [NOI2016] 网格 【割顶】【并查集】

题目分析:

答案显然只有{-1,0,1,2}四种。

对于答案等于-1的情况,只有两种情况,一种是只剩一只跳蚤,另一种是只剩两只跳蚤且他们四连通,这个很好判。

对于答案等于0的情况,那说明联通块大于1,把图离散出来连边并查集判就可以了。

对于答案等于1的情况,我们要考虑唯一的联通块是否存在割顶,具体的,我们发现答案只可能是有蛐蛐的格子旁边的八个格子(n=1或m=1除外),那么把它们提取出来单独建点,而其它的离散,跑一边割顶就可以做了。

剩下的输出2.

代码:

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 
  4 const int maxn = 2012000;
  5 
  6 int n,m,c,tot;
  7 pair<int,int> pr[maxn];
  8 vector<pair<int,int> > vec[maxn];
  9 int arr[maxn],mlgb[maxn],isg[maxn];
 10 vector<int> g[maxn];
 11 int dx[8]={0,0,1,-1,1,-1,1,-1};
 12 int dy[8]={1,-1,0,0,1,-1,-1,1};
 13 int chk,pre[maxn];
 14 int low[maxn],dfn[maxn],cl,fa[maxn];
 15 
 16 void init(){
 17     memset(pr,0,sizeof(pr));
 18     for(int i=0;i<=tot;i++) low[i]=dfn[i]=fa[i]=isg[i]=arr[i]=0;
 19     for(int i=0;i<=tot;i++) vec[i].clear(),g[i].clear();
 20     cl = chk = n = m = c = tot = 0;
 21 }
 22 
 23 int found(int x){
 24     int rx = x; while(pre[rx] != rx) rx = pre[rx];
 25     while(pre[x] != rx){int tmp = pre[x]; pre[x] = rx; x = tmp;}
 26     return rx;
 27 }
 28 
 29 int pd0(){
 30     sort(pr+1,pr+c+1);pr[0] = make_pair(0,m+10);
 31     int tnum = 0,pnum = 0;
 32     int zt = 0;
 33     for(int i=1;i<=c;i++) arr[++zt]=pr[i].first-1,arr[++zt]=pr[i].first+1,arr[++zt]=pr[i].first;
 34     sort(arr+1,arr+zt+1); zt = unique(arr+1,arr+zt+1)-arr-1;
 35     while(arr[zt] == n+1)zt--;
 36     for(int i=1;i<=zt;i++){
 37     if(arr[i] == 0) continue;
 38     if(arr[i] != arr[i-1]+1){vec[++tnum].push_back(make_pair(1,m));tot++;}
 39     tnum++;
 40     int lst = lower_bound(pr+1,pr+c+1,make_pair(arr[i]-1,0))-pr;
 41     int now = lower_bound(pr+1,pr+c+1,make_pair(arr[i],0))-pr;
 42     if(pr[now].first != arr[i]) now = 0;
 43     int imp=0;while(lst<=c&&pr[lst].first<=arr[i]+1) mlgb[++imp]=pr[lst].second,lst++;
 44     sort(mlgb+1,mlgb+imp+1); imp = unique(mlgb+1,mlgb+imp+1)-mlgb-1;
 45     int z = 1;int j = now,k = 1;
 46     while(z <= m){
 47         if(k > imp){vec[tnum].push_back(make_pair(z,m));tot++;z=m+1;break;}
 48         while(pr[j].first==arr[i]&&pr[j].second<mlgb[k])j++;
 49         if(z < mlgb[k]-1){vec[tnum].push_back(make_pair(z,mlgb[k]-2));tot++;z = mlgb[k]-1;}
 50         if(z < mlgb[k]){isg[++tot]=1;vec[tnum].push_back(make_pair(z,mlgb[k]-1));z = mlgb[k];}
 51         if(z==mlgb[k]&&(!(pr[j].first==arr[i]&&pr[j].second==mlgb[k]))){
 52         isg[++tot]=1;vec[tnum].push_back(make_pair(z,mlgb[k]));z = mlgb[k]+1;
 53         }else z = mlgb[k]+1;
 54         if(z > m) break;
 55         while(pr[j].first==arr[i]&&pr[j].second<mlgb[k]+1)j++;
 56         if(!(pr[j].first==arr[i]&&pr[j].second==mlgb[k]+1)){
 57         isg[++tot]=1;vec[tnum].push_back(make_pair(z,mlgb[k]+1));z = mlgb[k]+2;
 58         }
 59         k++;
 60     }
 61     }
 62     if(arr[zt] != n){vec[++tnum].push_back(make_pair(1,m));tot++;}
 63     for(int i=0;i<tot;i++) pre[i] = i;
 64     for(int i=1;i<tnum;i++){
 65     int k = 0;
 66     for(int j=0;j<vec[i].size();j++){
 67         while(k<vec[i+1].size()&&vec[i+1][k].second < vec[i][j].first) k++;
 68         while(k<vec[i+1].size()&&vec[i+1][k].second <= vec[i][j].second){
 69         g[pnum+j].push_back(pnum+vec[i].size()+k);
 70         g[pnum+vec[i].size()+k].push_back(pnum+j);
 71         pre[found(pnum+j)] = found(pnum+vec[i].size()+k); k++;
 72         }
 73         if(k<vec[i+1].size()&&vec[i+1][k].first <= vec[i][j].second){
 74         g[pnum+j].push_back(pnum+vec[i].size()+k);
 75         g[pnum+vec[i].size()+k].push_back(pnum+j);
 76         pre[found(pnum+j)] = found(pnum+vec[i].size()+k);
 77         }
 78     }
 79     pnum += vec[i].size();
 80     }
 81     pnum = 0;
 82     for(int i=1;i<=tnum;i++){
 83     for(int j=1;j<vec[i].size();j++){
 84         if(vec[i][j].first == vec[i][j-1].second+1){
 85         g[pnum+j].push_back(pnum+j-1);
 86         g[pnum+j-1].push_back(pnum+j);
 87         pre[found(pnum+j)] = found(pnum+j-1);
 88         }
 89     }
 90     pnum += vec[i].size();
 91     }
 92     int hh = 0;
 93     for(int i=0;i<tot;i++){if(pre[i] == i) hh++;}
 94     if(hh>1) return 1; else return 0;
 95 }
 96 
 97 void Tarjan(int now){
 98     low[now] = dfn[now] = ++cl;
 99     for(int i=0;i<g[now].size();i++){
100     if(g[now][i] == fa[now]) continue; 
101     if(dfn[g[now][i]] > dfn[now]) continue;
102     if(dfn[g[now][i]] == 0){
103         fa[g[now][i]] = now;Tarjan(g[now][i]);
104         low[now] = min(low[now],low[g[now][i]]);
105     }else{low[now] = min(low[now],dfn[g[now][i]]);}
106     }
107     if(isg[now+1]==0)return;
108     if(now != 0){
109     for(int i=0;i<g[now].size();i++){
110         if(fa[g[now][i]] != now) continue;
111         if(low[g[now][i]] >= dfn[now]){chk=1;}
112     }
113     }else{
114     int nh = 0;
115     for(int i=0;i<g[now].size();i++){if(fa[g[now][i]] == now){nh++;}}
116     if(nh > 1) chk++;
117     }
118 }
119 
120 void read(){
121     scanf("%d%d%d",&n,&m,&c);
122     for(int i=1;i<=c;i++){scanf("%d%d",&pr[i].first,&pr[i].second);}
123 }
124 
125 void work(){
126     if(1ll*n*m-c <= 1){puts("-1");return;}
127     if(1ll*n*m-c == 2){
128     sort(pr+1,pr+c+1); pair<int,int> l1,l2;
129     for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){
130         int z = lower_bound(pr+1,pr+c+1,make_pair(i,j))-pr;
131         if(pr[z] == make_pair(i,j)) continue;
132         if(l1 != make_pair(0,0)) l2=make_pair(i,j); else l1=make_pair(i,j);
133     }
134     if(abs(l1.first-l2.first)+abs(l1.second-l2.second)==1){puts("-1");}
135     else puts("0");
136     return;
137     }
138     if(pd0()) {puts("0");return;}
139     if(n == 1 || m == 1){puts("1");return;}
140     Tarjan(0);
141     if(chk){puts("1");return;}
142     else puts("2");
143 }
144 
145 int main(){
146     int Tmp; scanf("%d",&Tmp);
147     while(Tmp--){
148     init();
149     read();
150     work();
151     }
152     return 0;
153 }
原文地址:https://www.cnblogs.com/Menhera/p/10799316.html