SGU 286 Ancient decoration(Euler路径+二分匹配)

http://acm.sgu.ru/problem.php?contest=0&problem=286

先找欧拉回路,再做二分匹配,输出匹配

有一道题和这个很像:HDU 3551 Hard Problem(带花树匹配)

但是这道题用带花树内存开不下匹配的数组。。。

  1 /**
  2 *先找欧拉回路,再做二分匹配,输出匹配
  3 *场上想的是用带花树做,因为之前做过一道类似的题:HDU 3551 Hard Problem
  4 *设边e(u,v),则将(u,e) (v,e') (e,e')连起来
  5 *注意u有deg[u]-D[u]-1个顶点,v同样,e,e'表示将边e拆成e和e'两个顶点
  6 *然后用带花树算法做匹配,如果有完美匹配则输出YES,并输出匹配,否则输出NO。
  7 *但是这种做法做匹配数组开不下。。。(90000*90000的。。。)
  8 *
  9 *@Author: xysmlx xiaohai
 10 */
 11 //#pragma comment(linker, "/STACK:102400000,102400000")
 12 #include<cstdio>
 13 #include<iostream>
 14 #include<cstring>
 15 #include<string>
 16 #include<cmath>
 17 #include<set>
 18 #include<list>
 19 #include<map>
 20 #include<iterator>
 21 #include<cstdlib>
 22 #include<vector>
 23 #include<queue>
 24 #include<stack>
 25 #include<algorithm>
 26 #include<functional>
 27 using namespace std;
 28 typedef long long LL;
 29 #define ROUND(x) round(x)
 30 #define FLOOR(x) floor(x)
 31 #define CEIL(x) ceil(x)
 32 const int maxn=510;
 33 const int inf=0x3f3f3f3f;
 34 const LL inf64=0x3f3f3f3f3f3f3f3fLL;
 35 const double INF=1e30;
 36 const double eps=1e-6;
 37 int n,m,k;
 38 int no[maxn][maxn];
 39 int deg[maxn];
 40 
 41 /**
 42 *大数据二分图匹配:Hopcroft-Karp($O(sqrt{v}E)$)
 43 *适用于数据较大的二分匹配(从0到n-1)
 44 *输入:Nx,Ny,g[][]
 45 *输出:res=MaxMatch();Mx[]My[]
 46 */
 47 //const int maxn=0;
 48 //const int inf=0x3f3f3f3f;
 49 int g[maxn][maxn],Mx[maxn],My[maxn],Nx,Ny;
 50 int dx[maxn],dy[maxn],dis;
 51 bool vst[maxn];
 52 bool searchP()
 53 {
 54     queue<int>Q;
 55     dis=inf;
 56     memset(dx,-1,sizeof(dx));
 57     memset(dy,-1,sizeof(dy));
 58     for(int i=0; i<Nx; i++)
 59         if(Mx[i]==-1)
 60         {
 61             Q.push(i);
 62             dx[i]=0;
 63         }
 64     while(!Q.empty())
 65     {
 66         int u=Q.front();
 67         Q.pop();
 68         if(dx[u]>dis)  break;
 69         for(int v=0; v<Ny; v++)
 70             if(g[u][v]&&dy[v]==-1)
 71             {
 72                 dy[v]=dx[u]+1;
 73                 if(My[v]==-1)  dis=dy[v];
 74                 else
 75                 {
 76                     dx[My[v]]=dy[v]+1;
 77                     Q.push(My[v]);
 78                 }
 79             }
 80     }
 81     return dis!=inf;
 82 }
 83 bool DFS(int u)
 84 {
 85     for(int v=0; v<Ny; v++)
 86         if(!vst[v]&&g[u][v]&&dy[v]==dx[u]+1)
 87         {
 88             vst[v]=1;
 89             if(My[v]!=-1&&dy[v]==dis) continue;
 90             if(My[v]==-1||DFS(My[v]))
 91             {
 92                 My[v]=u;
 93                 Mx[u]=v;
 94                 return 1;
 95             }
 96         }
 97     return 0;
 98 }
 99 int MaxMatch()
100 {
101     int res=0;
102     memset(Mx,-1,sizeof(Mx));
103     memset(My,-1,sizeof(My));
104     while(searchP())
105     {
106         memset(vst,0,sizeof(vst));
107         for(int i=0; i<Nx; i++)
108             if(Mx[i]==-1&&DFS(i))  res++;
109     }
110     return res;
111 }
112 
113 /**
114 *Euler 路径(未知复杂度)
115 *首先计算出每个点的度数degree,然后调用euler函数,返回值为欧拉路径长度
116 *输入:n,g[][](邻接矩阵),deg[]
117 *输出:euler(),在相应地方处理
118 */
119 void euler()
120 {
121     for(int i=0; i<n; i++)
122     {
123         if(deg[i])
124         {
125             int u=i;
126             while(1)
127             {
128                 for(int j=0; j<n; j++)
129                 {
130                     if(g[u][j]&&g[j][u])
131                     {
132                         g[j][u]=0;///欧拉路径的边,在这里处理
133                         deg[u]--,deg[i]--;
134                         u=j;
135                         break;
136                     }
137                 }
138                 if(u==i) break;
139             }
140         }
141     }
142 }
143 
144 void init()
145 {
146     memset(g,0,sizeof(g));
147     memset(no,0,sizeof(no));
148     memset(deg,0,sizeof(deg));
149     Nx=n;
150     Ny=n;
151     m=n*k/2;
152 }
153 void input()
154 {
155     for(int i=1; i<=m; i++)
156     {
157         int u,v;
158         scanf("%d%d",&u,&v);
159         --u,--v;
160         g[u][v]=g[v][u]=1;
161         no[u][v]=no[v][u]=i;
162         deg[v]++,deg[u]++;
163     }
164 }
165 void solve()
166 {
167     euler();
168 
169     int ret=MaxMatch();
170     if(ret<n)
171     {
172         puts("NO");
173         return;
174     }
175     puts("YES");
176     for(int i=0;i<n;i++)
177         printf("%d
",no[Mx[i]][i]);
178 }
179 int main()
180 {
181 //    std::ios_base::sync_with_stdio(false);
182 //    freopen("in.cpp","r",stdin);
183     scanf("%d%d",&n,&k);
184     init();
185     input();
186     solve();
187     return 0;
188 }
View Code
原文地址:https://www.cnblogs.com/xysmlx/p/3290442.html