zoukankan      html  css  js  c++  java
  • ZOJ 3316 Game (带花树算法)

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=3726

    将同在L范围内的棋子建立边,然后做一般图的最大匹配(带花树算法),如果是完美匹配则输出YES;否则输出NO。

    如果有完美匹配的话,顺着匹配拿掉棋子即可使后手赢。

      1 //#pragma comment(linker, "/STACK:102400000,102400000")
      2 #include<cstdio>
      3 #include<iostream>
      4 #include<cstring>
      5 #include<string>
      6 #include<cmath>
      7 #include<set>
      8 #include<list>
      9 #include<map>
     10 #include<iterator>
     11 #include<cstdlib>
     12 #include<vector>
     13 #include<queue>
     14 #include<stack>
     15 #include<algorithm>
     16 #include<functional>
     17 using namespace std;
     18 typedef long long LL;
     19 #define ROUND(x) round(x)
     20 #define FLOOR(x) floor(x)
     21 #define CEIL(x) ceil(x)
     22 const int maxn=500;
     23 const int inf=0x3f3f3f3f;
     24 const LL inf64=0x3f3f3f3f3f3f3f3fLL;
     25 const double INF=1e30;
     26 const double eps=1e-6;
     27 
     28 /**
     29 *一般图的最大基数匹配:带花树算法
     30 *输入:g[][],n(输入从0到n-1,用addEdge()加边)
     31 *输出:gao()(最大匹配数),match[](匹配)
     32 */
     33 //const int maxn=0;
     34 struct Matching
     35 {
     36     deque<int> Q;
     37     int n;
     38     //g[i][j]存放关系图:i,j是否有边,match[i]存放i所匹配的点
     39     bool g[maxn][maxn],inque[maxn],inblossom[maxn],inpath[maxn];
     40     int match[maxn],pre[maxn],base[maxn];
     41 
     42     //找公共祖先
     43     int findancestor(int u,int v)
     44     {
     45         memset(inpath,0,sizeof(inpath));
     46         while(1)
     47         {
     48             u=base[u];
     49             inpath[u]=true;
     50             if(match[u]==-1)break;
     51             u=pre[match[u]];
     52         }
     53         while(1)
     54         {
     55             v=base[v];
     56             if(inpath[v])return v;
     57             v=pre[match[v]];
     58         }
     59     }
     60 
     61     //压缩花
     62     void reset(int u,int anc)
     63     {
     64         while(u!=anc)
     65         {
     66             int v=match[u];
     67             inblossom[base[u]]=1;
     68             inblossom[base[v]]=1;
     69             v=pre[v];
     70             if(base[v]!=anc)pre[v]=match[u];
     71             u=v;
     72         }
     73     }
     74 
     75     void contract(int u,int v,int n)
     76     {
     77         int anc=findancestor(u,v);
     78         //SET(inblossom,0);
     79         memset(inblossom,0,sizeof(inblossom));
     80         reset(u,anc);
     81         reset(v,anc);
     82         if(base[u]!=anc)pre[u]=v;
     83         if(base[v]!=anc)pre[v]=u;
     84         for(int i=1; i<=n; i++)
     85             if(inblossom[base[i]])
     86             {
     87                 base[i]=anc;
     88                 if(!inque[i])
     89                 {
     90                     Q.push_back(i);
     91                     inque[i]=1;
     92                 }
     93             }
     94     }
     95 
     96     bool dfs(int S,int n)
     97     {
     98         for(int i=0; i<=n; i++)pre[i]=-1,inque[i]=0,base[i]=i;
     99         Q.clear();
    100         Q.push_back(S);
    101         inque[S]=1;
    102         while(!Q.empty())
    103         {
    104             int u=Q.front();
    105             Q.pop_front();
    106             for(int v=1; v<=n; v++)
    107             {
    108                 if(g[u][v]&&base[v]!=base[u]&&match[u]!=v)
    109                 {
    110                     if(v==S||(match[v]!=-1&&pre[match[v]]!=-1))contract(u,v,n);
    111                     else if(pre[v]==-1)
    112                     {
    113                         pre[v]=u;
    114                         if(match[v]!=-1)Q.push_back(match[v]),inque[match[v]]=1;
    115                         else
    116                         {
    117                             u=v;
    118                             while(u!=-1)
    119                             {
    120                                 v=pre[u];
    121                                 int w=match[v];
    122                                 match[u]=v;
    123                                 match[v]=u;
    124                                 u=w;
    125                             }
    126                             return true;
    127                         }
    128                     }
    129                 }
    130             }
    131         }
    132         return false;
    133     }
    134 
    135     void init(int n)
    136     {
    137         this->n = n;
    138         memset(match,-1,sizeof(match));
    139         memset(g,0,sizeof(g));
    140     }
    141 
    142     void addEdge(int a, int b)
    143     {
    144         ++a;
    145         ++b;
    146         g[a][b] = g[b][a] = 1;
    147     }
    148 
    149     int gao()
    150     {
    151         int ans = 0;
    152         for (int i = 1; i <= n; ++i)
    153             if (match[i] == -1 && dfs(i, n))
    154                 ++ans;
    155         return ans;
    156     }
    157 } match;
    158 
    159 int n,m,L;
    160 vector<pair<int,int> > node;
    161 int dist(pair<int,int> A,pair<int,int> B)
    162 {
    163     return abs(A.first-B.first)+abs(A.second-B.second);
    164 }
    165 void init()
    166 {
    167     node.clear();
    168     match.init(m);
    169 }
    170 void input()
    171 {
    172     n=m;
    173     int u,v;
    174     while(m--)
    175     {
    176         scanf("%d%d",&u,&v);
    177         node.push_back(pair<int,int>(u,v));
    178     }
    179     scanf("%d",&L);
    180     pair<int,int> x,y;
    181     for(int i=0;i<node.size();i++)
    182     {
    183         x=node[i];
    184         for(int j=0;j<node.size();j++)
    185         {
    186             if(i==j) continue;
    187             y=node[j];
    188             if(dist(x,y)<=L) match.addEdge(i,j);
    189         }
    190     }
    191 }
    192 void solve()
    193 {
    194     if(match.gao()*2==n) puts("YES");
    195     else puts("NO");
    196 }
    197 int main()
    198 {
    199 //    std::ios_base::sync_with_stdio(false);
    200 //    freopen("in.cpp","r",stdin);
    201     while(~scanf("%d",&m))
    202     {
    203         init();
    204         input();
    205         solve();
    206     }
    207     return 0;
    208 }
    View Code
  • 相关阅读:
    洛谷 P3128 [ USACO15DEC ] 最大流Max Flow —— 树上差分
    洛谷 P3953 [ NOIP 2017 ] 逛公园 —— 最短路DP
    bzoj 3231 [ Sdoi 2008 ] 递归数列 —— 矩阵乘法
    bzoj 1024 [ SCOI 2009 ] 生日快乐 —— 递归
    hdu 5823 color II —— 子集DP
    bzoj 1093 [ ZJOI 2007 ] 最大半连通子图 —— 拓扑+DP
    洛谷 P3959 NOIP2017 宝藏 —— 状压搜索
    最短路(模板
    线段树 扫描线
    Dijkstra算法
  • 原文地址:https://www.cnblogs.com/xysmlx/p/3273249.html
Copyright © 2011-2022 走看看