• 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 }
  • 相关阅读:
    PTA 两个有序链表序列的合并
    PTA 递增的整数序列链表的插入
    PTA 链表逆置
    PTA 带头结点的链式表操作集
    _KPCR, _NT_TIB, _KPRCB
    FSOP
    逆向PspCreateProcess
    寒假训练 [GKCTF2020]Domo(4/250) 劫持vtable
    IO_FILE利用与劫持vtables控制程序流程、FSOP
    线程结构
  • 原文地址:https://www.cnblogs.com/Menhera/p/10799316.html
Copyright © 2020-2023  润新知