码迷,mamicode.com
首页 > 其他好文 > 详细

Codeforces 627F Island Puzzle - 构造

时间:2018-10-31 23:30:44      阅读:696      评论:0      收藏:0      [点我收藏+]

标签:getc   方案   等价   lld   要求   wal   solution   ||   rev   

题目传送门

  传送门I

  传送门II

  传送门III

题目大意

  (八数码问题的树上版本)。

  已经存在解的时候直接输出最少的移动步数。

  否则允许加入一条边,要求输出边的端点以及最少的移动步数。

  仍然无解输出-1.

  不添加边的时候方案是唯一的:直接把0移动到目的地,然后判断是否有解。

  考虑把$0$移动到目的后,把0当做根。因为操作可逆,这个时候是否存在解与原图是否存在解等价。

  考虑此时0走到一个环上转移圈的意义:把进入点先拿出来,转上若干圈,回到起点,把原来的进入点放回环中。

  所以所有不合法的位置只有两种情况:

  1. 构成一条子节点到父节点的链。边连在最深点和最浅点的父节点。
  2. 连成一条除了最高点位置正确的链。

  然后可以任意再环上找一个点,计算需要转动的圈数,然后判断一下是否可行。

  于是我们顺利地判断了解的存在性。考虑怎么计算最短的步数。

  如果环不在0走到根的路径上,那么需要花费额外的步数走到它。

  如果在,就考虑是顺着路径绕还是逆着路径绕。

  表示被绕环的方向坑死,WA了一天(向上走的时候可能与环的存储顺序相反)。

Code

  1 /**
  2  * Codeforces
  3  * Problem#627F
  4  * Accepted
  5  * Time: 233ms
  6  * Memory: 15500k
  7  */
  8 #include <algorithm>
  9 #include <iostream>
 10 #include <cassert>
 11 #include <cstdlib>
 12 #include <cstdio>
 13 #include <vector>
 14 #ifndef WIN32
 15 #define Auto "%lld"
 16 #else
 17 #define Auto "%I64d"
 18 #endif
 19 using namespace std;
 20 typedef bool boolean;
 21 
 22 const int N = 2e5 + 5;
 23 
 24 #define ll long long
 25 
 26 template <typename T>
 27 void pfill(T* pst, const T* ped, T val) {
 28     for ( ; pst != ped; *(pst++) = val);
 29 }
 30 
 31 FILE* fin = stdin;
 32 FILE* fout = stdout;
 33 
 34 int n;
 35 int pu, pv;
 36 int rta = 1, rtb = 1;
 37 vector<int> cir;
 38 int ar[N], br[N];
 39 int dep[N], fa[N];
 40 boolean inc[N], vis[N];
 41 vector<int> g[N];
 42 
 43 inline void init() {
 44     fscanf(fin, "%d", &n);
 45     for (int i = 1; i <= n; i++)
 46         fscanf(fin, "%d", ar + i);
 47     for (int i = 1; i <= n; i++)
 48         fscanf(fin, "%d", br + i);
 49     for (int i = 1; i <= n && ar[i]; rta = ++i);
 50     for (int i = 1; i <= n && br[i]; rtb = ++i);
 51     for (int i = 1, u, v; i < n; i++) {
 52         fscanf(fin, "%d%d", &u, &v);
 53         g[u].push_back(v);
 54         g[v].push_back(u);
 55     }
 56 }
 57 
 58 void dfs(int p, int fa) {
 59     dep[p] = dep[fa] + 1, ::fa[p] = fa;
 60     for (auto e : g[p])
 61         if (e ^ fa)
 62             dfs(e, p);
 63 }
 64 
 65 int getCircle() {     // 0 : no circle, -1 : no solution, 1: there exist a circle
 66     int A = 0, B = 0, g;
 67     for (int i = 1; i <= n; i++)
 68         if (ar[i] != br[i] && (!A || dep[i] > dep[A]))
 69             A = i;
 70     for (int p = A; ar[p] != br[p]; p = fa[p])
 71         cir.push_back(p), inc[p] = true;
 72     if (!A)
 73         return 0;
 74     for (int i = 1; i <= n; i++)
 75         if (!inc[i] && ar[i] != br[i] && (!B || dep[i] > dep[B]))
 76             B = i;
 77     if (B) {
 78         int s = cir.size();
 79         for (g = B; ar[g] != br[g] && !inc[g]; g = fa[g])
 80             cir.push_back(g), inc[g] = true;
 81         reverse(cir.begin() + s, cir.end());
 82     } else
 83         g = B = fa[cir.back()];
 84     
 85     if (inc[g])
 86         return -1;
 87     for (int i = 1; i <= n; i++)
 88         if (ar[i] != br[i] && !inc[i])
 89             return -1;
 90     for (int i = A; i != g; i = fa[i])
 91         if (!inc[i])
 92             return -1;
 93     for (int i = B; i != g; i = fa[i])
 94         if (!inc[i])
 95             return -1;
 96 
 97     pu = A, pv = B;
 98     if (pu > pv)
 99         swap(pu, pv);
100     return 1;
101 }
102 
103 inline void solve() {
104     dfs(rtb, 0);
105     for (int p = rta; fa[p]; p = fa[p])
106         swap(ar[fa[p]], ar[p]);
107     
108     int sta = getCircle(), mov = 0, walk = 0, g = 0;
109     ll res = dep[rta] - 1;
110     if (sta == -1) {
111         fputs("-1\n", fout);
112         return;
113     }
114 
115     if (!sta) {
116         fprintf(fout, "0 "Auto"\n", res);
117         return;
118     }
119 
120     int siz = cir.size();
121     for (int i = 0; i < siz; i++, mov++)
122         if (ar[cir[i]] == br[cir[0]])
123             break;
124     if (mov == siz) {
125         fputs("-1", fout);
126         return;
127     }
128     for (int i = 0; i < siz; i++)
129         if (br[cir[i]] ^ ar[cir[(i + mov) % siz]]) {
130             fputs("-1", fout);
131             return;
132         }
133     
134     for (int p = rta; p; p = fa[p])
135         vis[p] = true;
136     boolean aflag = true;
137     int sp = 0;
138     for (int i = 0; i + 1 < (signed) cir.size(); i++, sp++)
139         if (dep[cir[i + 1]] == dep[cir[i]])
140             break;
141     for (int i = 0; i <= sp && aflag; i++)
142         if (vis[cir[i]])
143             aflag = false;
144     for (auto p : cir)
145         walk += vis[p];    
146     if (walk) {
147         res -= walk;
148         if (aflag)
149             mov = siz - mov;
150         ll cmp1 = walk + (ll)mov * (siz + 1);
151         ll cmp2 = (ll)siz * (siz + 1) - cmp1;
152         res += min(cmp1, cmp2);
153     } else {
154         res += (ll) min(mov, siz - mov) * (siz + 1);
155         for (int i = 0; i < siz; i++)
156             if (!g || dep[cir[i]] < dep[g])
157                 g = cir[i];
158         g = fa[g];
159         for ( ; g && !vis[g]; res += 2, g = fa[g]);
160     }
161 
162     fprintf(fout, "%d %d "Auto"\n", pu, pv, res);
163 }
164 
165 int main() {
166     init();
167     solve();
168     return 0;
169 }

Codeforces 627F Island Puzzle - 构造

标签:getc   方案   等价   lld   要求   wal   solution   ||   rev   

原文地址:https://www.cnblogs.com/yyf0309/p/9880294.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!