C. Restore Graph (类bfs模拟+构造)

https://codeforces.com/problemset/problem/404/C


题意翻译

对于n个顶点,我们对其进行加边操作!

首先题目会给你n,k 再给n个数 第 i 个为d_idi​,就是从某一点开始的到i的最短路。 我们对其加边使其满足这最后的答案,如果不能满足,就是输出-1

一个顶点的度 应该不大于 k Translated by @Bartholomew

输入输出样例

输入 #1复制

3 2
0 1 1

输出 #1复制

3
1 2
1 3
3 2

输入 #2复制

4 2
2 0 1 3

输出 #2复制

3
1 3
1 4
2 3

输入 #3复制

3 1
0 0 0

输出 #3复制

-1

思路:把长度为1,2,3......的分别存到队列和vector<int>mp[maxn]的桶里,然后对当前长度i的结点进行遍历,如果上一层(i-1)的队里不空并且那个的degree[]<k,那么连边存下来,不然就把这个点弹出来。

#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int maxn=1e5+100;
typedef long long LL;
struct node{
	LL x,y;
}nodes[maxn];
queue<LL> q[maxn];
vector<LL> mp[maxn]; 
LL deg[maxn];
int main(void)
{
  cin.tie(0);std::ios::sync_with_stdio(false);
  LL n,k;cin>>n>>k;
  LL flag=0;
  for(LL i=1;i<=n;i++){
  	LL _x;cin>>_x;
  	if(_x==0) flag++;
  	q[_x].push(i);
  	mp[_x].push_back(i);
  }
  if(flag>=2){
  	cout<<"-1"<<endl;return 0;
  }
  LL cnt=0;
  for(LL i=1;i<=n;i++){
  	for(LL j=0;j<mp[i].size();j++){
  		LL u=-1;
  		LL v=mp[i][j];
  		while(!q[i-1].empty())
  		{
  			u=q[i-1].front();
			if(deg[u]<k) break;
			else q[i-1].pop();  	
		}
		if(u!=-1&&deg[u]<k)
		{
			deg[u]++;
			deg[v]++;
			nodes[++cnt].x=u;
			nodes[cnt].y=v;
		}
		else{
			cout<<"-1"<<endl;
			return 0;
		}
	}
  }
  cout<<cnt<<endl;
  for(LL i=1;i<=cnt;i++){
  	cout<<nodes[i].x<<" "<<nodes[i].y<<endl;
  }
return 0;
}

猜你喜欢

转载自blog.csdn.net/zstuyyyyccccbbbb/article/details/108510422