codeforces 404C - Restore Graph

題目鏈接:http://codeforces.com/problemset/problem/404/C

題目大意:n個點,每個點上最多有m個點與其相連,某點到所有點的最短路,判斷是否能還原這張圖,如果可以輸出相連的邊。

題目分析:首先需要找到原點,如果一個點的距離是0的話,則是起點,但是肯定只有一個。然後判斷一下其餘距離的點是不是都是在[1,k]範圍就行了。

代碼參考:

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<cstdio>
#include<vector>
#include<string>
#include<cstring>
#include<sstream>
#include<iostream>
#include<algorithm>
#include<functional>
using namespace std;
typedef long long LL;
const int N = 1 << 17;
vector<int> v[N];
int main()
{
	int n, m, i, j, k, x, y, z, r;
	while (~scanf("%d%d", &n, &k))
	{
		for (i = 0; i < N; ++i)//初始化
		{
			v[i].clear();
		}

		int M = -1;//求最遠的距離

		for (i = 1; i <= n; ++i)
		{
			scanf("%d", &x);
			v[x].push_back(i);//保存第i個點的距離爲x
			M = max(M, x);
		}

		if (v[0].size() != 1 || v[1].size() > k)//如果起點不唯一或者和起點的點數大於k
		{
			puts("-1");
			continue;
		}

		bool f = true;

		for (i = 2; i <= M; ++i)//枚舉每個距離
		{
			if (v[i - 1].size() * (k - 1LL) < v[i].size())//每個點與前面的點相連之後還剩下k-1個位置可以和後面的點相連
			{//v[i - 1].size() * (k - 1LL)可能超出int範圍
				puts("-1");
				f = false;
				break;
			}
		}

		if (f)
		{
			printf("%d\n", n - 1);//最小生成樹由n-1條邊連接

			for (i = 0; i < M; ++i)//枚舉每個距離
			{
				int cnt = 1;//統計已經和幾條邊相連
				j = r = 0;

				while (j < v[i].size() && r < v[i + 1].size())
				{
					if (i > 0 && cnt < k)
					{
						printf("%d %d\n", v[i][j], v[i + 1][r]);
						cnt++;
						r++;
					}
					else if (i == 0 && cnt <= k)//i==0時特判
					{
						printf("%d %d\n", v[i][j], v[i + 1][r]);
						cnt++;
						r++;
					}
					else
					{
						j++;//如果超過k了,就將剩下的點接在另外的等價的點上
						cnt = 1;
					}
				}

			}
		}
	}

	return 0;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章