hdu3446 daizhenyang's chess,一般图匹配
来源:互联网 发布:大学生java培训课程 编辑:程序博客网 时间:2024/05/19 20:59
hdu3446 daizhenyang's chess
一般图匹配问题。
将所有'.'的点之间可到达的建边。求最大匹配。
最后将K点加入,找增广路。
如果找到增广路,先手胜,否则后手胜。
证明比较容易(如果找到增广路,则先手可以找到一个包含偶数个点也就是奇数个边的路径,这样最后一次走的还是先手)。
一般图匹配问题。
将所有'.'的点之间可到达的建边。求最大匹配。
最后将K点加入,找增广路。
如果找到增广路,先手胜,否则后手胜。
证明比较容易(如果找到增广路,则先手可以找到一个包含偶数个点也就是奇数个边的路径,这样最后一次走的还是先手)。
#include<iostream>#include<cstdio>#include<cstring>#include<queue>using namespace std;#define Maxn 250int set[Maxn];int vis[Maxn],next[Maxn],mark[Maxn],spouse[Maxn];int q[Maxn*2],head,tail;int n;int tn,tm;int tlev=0;int di[]={-2,-2,-2,-2,-1,-1,-1,-1,-1,0,0,1,1,1,1,1,2,2,2,2};int dj[]={-2,-1,1,2,-2,-1,0,1,2,-1,1,-2,-1,0,1,2,-2,-1,1,2};int fi[Maxn],ne[Maxn*Maxn],to[Maxn*Maxn],te;void addedge(int u,int v){ //printf(" %d %d\n",u,v); te++;ne[te]=fi[u];fi[u]=te;to[te]=v;}int findset(int x){return x==set[x]?x:set[x]=findset(set[x]);}void mergeset(int x,int y){x=findset(x);y=findset(y);if (x!=y) set[x]=y;}int findlca(int u,int v){ tlev++; while(1){ if (u!=-1){ u=findset(u); if (vis[u]==tlev) return u; vis[u]=tlev; if (spouse[u]!=-1) u=next[spouse[u]]; else u=-1; } swap(u,v); }}void group(int a,int p){ int b,c; while(a!=p){ b=spouse[a];c=next[b]; if (findset(c)!=p) next[c]=b; if (mark[b]==2) mark[q[tail++]=b]=1; if (mark[c]==2) mark[q[tail++]=c]=1; mergeset(a,b); mergeset(b,c); a=c; }}void findaugment(int s){ int i,j,k,l,e,u,v,p; for(i=1;i<=n;++i){ next[i]=-1;set[i]=i;mark[i]=0;vis[i]=-1; } q[head=0]=s;tail=1;mark[s]=1; while(head<tail){ if (spouse[s]!=-1) break; u=q[head++]; for(e=fi[u];~e;e=ne[e]){ v=to[e]; if (spouse[u]!=v&&findset(u)!=findset(v)&&mark[v]!=2){ if (mark[v]==1){ p=findlca(u,v); if (findset(u)!=p) next[u]=v; if (findset(v)!=p) next[v]=u; group(u,p); group(v,p); } else if (spouse[v]==-1){ next[v]=u; for(j=v;j!=-1;){ k=next[j]; l=spouse[k]; spouse[k]=j;spouse[j]=k; j=l; } break; } else{ //spouse[v]!=-1 next[v]=u; mark[q[tail++]=spouse[v]]=1; mark[v]=2; } } } }}int work(){ int i,ret; for(i=1;i<=n;++i) spouse[i]=-1; for(i=1;i<=n;++i)if (spouse[i]==-1) findaugment(i); ret=0; for(i=1;i<=n;++i) if (~spouse[i]) ret++; return ret;}int abs(int x){return x<0?-x:x;}char s[20][20];int g[20][20];void makegraph(int i,int j,int func){ int d,vi,vj; for(d=0;d<20;++d){ vi=i+di[d]; vj=j+dj[d]; if (vi<0||vi>=tn||vj<0||vj>=tm) continue; if (g[vi][vj]==1) { addedge(i*tm+j+1,vi*tm+vj+1); if (func==2) addedge(vi*tm+vj+1,i*tm+j+1); } }}int main(){ int i,j,tcas,cas,sti,stj; scanf("%d",&tcas); for(cas=1;cas<=tcas;++cas){ scanf("%d%d",&tn,&tm); n=tn*tm; for(i=0;i<tn;++i){ scanf("%s",s[i]); } queue<int> qi,qj; memset(g,0,sizeof(g)); for(i=0;i<tn;++i){ for(j=0;j<tm;++j){ if (s[i][j]=='K') {sti=i;stj=j;} else if(s[i][j]=='.') {qi.push(i);qj.push(j);g[i][j]=1;} } } memset(fi,-1,sizeof(fi)); te=0; while(!qi.empty()){ i=qi.front();qi.pop(); j=qj.front();qj.pop(); makegraph(i,j,1); } work(); makegraph(sti,stj,2); findaugment(sti*tm+stj+1); printf("Case #%d: ",cas); if (spouse[sti*tm+stj+1]!=-1){ printf("daizhenyang win\n"); } else printf("daizhenyang lose\n"); } return 0;}
0 0
- hdu3446 daizhenyang's chess,一般图匹配
- hdu3446 daizhenyang's chess 【一般图匹配】
- hdu3537 Daizhenyang's Coin
- HDOJ 3537 Daizhenyang's Coin
- HDU 3537 Daizhenyang's Coin
- 【hdu 3537】Daizhenyang's Coin
- 一般图匹配带花树
- HDU4687 (一般图匹配)
- 一般图匹配带花树
- 一般图最大匹配
- 一般图最大匹配
- HDU3551 一般图最大匹配
- 带花树 一般图最大匹配
- 一般图匹配带花树模板
- uva753(一般图匹配)
- 一般图匹配--带花树算法
- [UOJ79]一般图最大匹配
- 一般图匹配带花树模板
- "/host.conf" E212: Can't open file for writing
- spring mvc 防止重复提交 token
- 看看你对编程语言了解多少
- Git目录 与 工作目录
- 使用LongListSelector控件按拼音分组
- hdu3446 daizhenyang's chess,一般图匹配
- 前端编程提高之旅(三)----浏览器兼容之IE6
- 局部内部类只能访问非final变量
- addChildViewController
- pl sql 连接oracleTNS-12541: TNS: 无监听程序(缺少tnsnames.ora和listener.ora文件)
- Freemarker_内置函数_数字、字符串、日期格式化
- Git索引
- Binder机制2---Binder的数据结构以及Binder驱动
- poj 2349 Arctic Network (prim算法)