UOJ 171 WC2016挑战NPC

Posted №〓→龙光←

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UOJ 171 WC2016挑战NPC相关的知识,希望对你有一定的参考价值。

  一开始还真没想到是一般图匹配这种模型(毕竟才会的带花树)

 

  把每一个盒子拆成3个,每一个可以放置进它的小球分别向这三个点连边,然后这三个点在连成一个三元环,最终答案就是小球数目-匹配数。

  由于是一般图,所以套一个带花树就可以了。

  

  NOTICE:寻找增广路时,应该从球先找起,这样子才保证了每个球有地方放置。

 

  


  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<vector>
  5 #include<cstdlib>
  6 #include<cmath>
  7 #include<cstring>
  8 using namespace std;
  9 #define maxn 10010
 10 #define llg long long 
 11 #define yyj(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
 12 llg n,m,sett,father[maxn],pre[maxn],match[maxn],vis[maxn],id[maxn],dl[maxn*10],head,tail,ans,T,totn,e;
 13 llg c[1000][1000];
 14 
 15 vector<llg> a[maxn];
 16 
 17 llg find(llg x){if (father[x]!=x) father[x]=find(father[x]); return father[x];}
 18 
 19 llg lca(llg x,llg y)
 20 {
 21     sett++;
 22     while (vis[x]!=sett)
 23     {
 24         if (x)
 25         {
 26             x=find(x);
 27             if (vis[x]==sett) return x;
 28             vis[x]=sett;
 29             if (match[x]!=0) x=find(pre[match[x]]);
 30             else x=0;
 31         }
 32         
 33             swap(x,y);
 34     }
 35     return x;
 36 }
 37 
 38 void change(llg x,llg y,llg fa)
 39 {
 40     llg z;
 41     while (find(x)!=fa)
 42     {
 43         pre[x]=y; z=match[x];
 44         if (id[z]==1) {id[z]=0,dl[++tail]=z;}
 45         if (find(z)==z) father[z]=fa;
 46         if (find(x)==x) father[x]=fa;
 47         y=z; x=pre[y];
 48     }
 49 }
 50 
 51 bool bfs(llg p)
 52 {
 53     llg x,w,v;
 54     for (llg i=1;i<=n;i++) id[i]=-1,father[i]=i;
 55     head=0,tail=1,dl[1]=p; id[p]=0;
 56     do
 57     {
 58         x=dl[++head],w=a[x].size();
 59         for (llg i=0;i<w;i++)
 60         {
 61             v=a[x][i];
 62             if (id[v]==-1)
 63             {
 64                 pre[v]=x;
 65                 id[v]=1;
 66                 if (!match[v])
 67                 {
 68                     llg last,t,now=v;
 69                     while (now!=0)
 70                     {
 71                         t=pre[now],last=match[t];
 72                         match[t]=now; match[now]=t;
 73                         now=last;// v=t;
 74                     }//把原lai的匹配和非匹配bian取反
 75                     return 1;
 76                 }
 77                 id[match[v]]=0,dl[++tail]=match[v];
 78             }
 79             else
 80                 if (id[v]==0 && find(v)!=find(x))
 81                 {
 82                     llg dad=lca(x,v);
 83                     change(x,v,dad);
 84                     change(v,x,dad);
 85                 }
 86         }
 87     }while (head!=tail);
 88     return 0;
 89 
 90 }
 91 
 92 void link(llg x,llg y) {a[x].push_back(y),a[y].push_back(x);}
 93 
 94 void init()
 95 {
 96     for (llg i=1;i<=n;i++) a[i].clear(),vis[i]=match[i]=pre[i]=father[i]=id[i]=dl[i]=0;
 97     //for (llg i=1;i<=n;i++) for (llg j=1;j<=n;j++) c[i][j]=c[j][i]=0;
 98     scanf("%lld%lld%lld",&n,&m,&e);
 99     totn=n;
100     llg x,y;
101     for (llg i=1;i<=e;i++)
102     {
103         scanf("%lld%lld",&x,&y);
104         
105         llg po=m*3+x;
106         link(po,y*3-2),link(po,y*3-1),link(po,y*3);
107         //a[x].push_back(y),a[y].push_back(x);
108     }
109     n=n+m*3;
110     for (llg i=1;i<=m;i++)
111     {
112         link(i*3-2,i*3-1),link(i*3-1,i*3),link(i*3,i*3-2);
113     }
114 }
115 
116 void oupt()
117 {
118     cout<<ans-totn<<endl;
119     for (llg i=1;i<=totn;i++)
120     {
121         printf("%lld ",(match[3*m+i]-1)/3+1);
122     }
123     printf("\\n");
124 }
125 
126 int main()
127 {
128     //yyj("a");
129     cin>>T;
130     while (T--)
131     {
132         ans=0;
133         init();
134         for (llg i=n;i>1;i--) 
135             if (!match[i] && bfs(i)) ans++;
136         oupt();
137     }    
138     return 0;
139 }

 

以上是关于UOJ 171 WC2016挑战NPC的主要内容,如果未能解决你的问题,请参考以下文章

[WC2016]挑战NPC

P4258 [WC2016]挑战NPC(一般图匹配)

[WC2016]挑战NPC

[WC2016]挑战NPC

BZOJ4405 [wc2016]挑战NPC

[WC2016]挑战NPC