题目链接:http://codeforces.com/contest/556/problem/C
题目意思:有 n 个数(1,2,...,n)组成 k 条链。第 i 条链由 mi 个数组成。每一秒只可以做其中一件事:(1)将链i连到只有一个数的链 j 中(链 i 的最大值比只由单个数组成的链 j 还要小);(2)将链上最大的数从链中分离。 然后我们最终是要得到一条1,2,3,。。。n。问最少需要连接的秒数。
不难推出,我们需要找到编号为 1 的链包含多少个数,然后对于此链的其他数,我们需要先分离然后连接。其他链也需要先分离再连接,注意,对于某条含有 x 个数的链,分离的秒数为 x - 1,而连接的秒数为 x 。 那现在问题就转化为如何找出包含 1 的链最长为多少(数是连续的!)
假设包含 1 的链为 cnt,那么最少的秒数应为 2(n - (k-1) - cnt) + (k-1) 。2(n - (k-1) - cnt) 这个表示所有需要分离和连接的总数,但由于每条链分离秒数是比连接的秒数少1的,所以需要加回 k -1 !
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 #include <algorithm> 6 using namespace std; 7 8 inline int Getint() 9 { 10 char ch = getchar(); 11 while (ch < '0' || ch > '9') 12 ch = getchar(); 13 int ret = 0; 14 while (ch >= '0' && ch <= '9') { 15 ret = ret * 10 + ch - '0'; 16 ch = getchar(); 17 } 18 return ret; 19 } 20 21 int main() 22 { 23 #ifndef ONLINE_JUDGE 24 freopen("in.txt", "r", stdin); 25 #endif // ONLINE_JUDGE 26 27 int n, k, m, a; 28 // while (scanf("%d%d", &n, &k) != EOF) { 29 n = Getint(), k = Getint(); 30 int cc = 0; 31 for (int i = 0; i < k; i++) { 32 m = Getint(), a = Getint(); 33 int cnt = 0; 34 if (a == 1) { 35 cnt = 1; // 序列第一个数就是 1 ,否则就是序中或序尾出现 1 36 } 37 for (int j = 2; j <= m; j++) { 38 a = Getint(); 39 if (cnt == j-1 && a == j) { 40 cnt++; 41 } 42 } 43 if (cnt) cc = cnt; 44 } 45 printf("%d ", 2*(n-(k-1)-cc)+(k-1)); 46 // } 47 return 0; 48 }