构造具有度数约束的任何二分图

时间:2016-10-22 16:05:12

标签: algorithm graph

我们需要在两个部分上构造一个每个都有N个顶点的二分图,并且边的总数等于M.

  • 左侧的顶点编号为1到N.
  • 右侧的顶点也从1到N编号。
  • 每个顶点的度数大于或等于X,并且小于或等于Y.即对于所有v,X≤deg(v)≤Y

给定四个整数N,M,X,Y,我们需要构造一些满足该性质的二分图。如果没有任何这样的图表,那么也告诉他们。

示例: 如果N = 2,则M = 3,X = 1且Y = 2 那么二分图中的3个边将是:(1,1),(2,2)和(1,2)

如果N = 2,M = 3,X = 1且Y = 1则不存在二分图。

如果

,如何解决这个问题
1 ≤ N ≤ 100
1 ≤ X ≤ Y ≤ N 
0 ≤ M ≤ N * N

原始问题link

2 个答案:

答案 0 :(得分:1)

显然,变量需要满足:

X * N <= M <= Y * N

否则,将无法解决。

找到边缘可以在波浪中完成。首先将第一组中的每个节点i连接到第二组中的相应节点i。在下一个wave中,将i(i + 1) mod N联系起来。然后i(i + 2) mod N一样。这将使每个顶点中的每个顶点的度数增加一个。只要构造了M边,就停止。这也可能发生在浪潮中。

答案 1 :(得分:0)

ACM ICPC 2016年印度初步问题。

Link

比赛现已结束。我无法提交答案(即将在结束前10秒提交代码并且我的互联网停止工作)。

在问题的OP版本中,

d相当于X

在问题的OP版本中,

D相当于Y

t是测试用例的数量。

我根据链接中的原始问题制作了代码。

逻辑类似于 Nico Schertler是一个。我的复杂性会更多一些,因为我没有在第i+x次迭代中将i节点连接到x,而是使用了一个集合来查找未连接的第一个元素。范围[1..N]并连接它们。

这是我的代码:

#include <bits/stdc++.h>
using namespace std;


int main() {

    int t, n, m, d, D;
    cin >> t;
    while(t--) {
        cin >> n >> m >> d >> D;
        if(n*D < m || n*d > m)
            printf("-1\n");
        else {
            vector <set <int> > v(n);
            int edges = 0, count = 0;
            while(count != d) {
                for(int i = 0; i < n; i++) {
                    for(int j = 0; j < n; j++) {
                        if(v[i].find(j) == v[i].end()) {
                            v[i].insert(j);
                            ++edges;
                            break;
                        }
                        if(edges == m)
                            break;
                    }
                    if(edges == m)
                        break;
                }   
                ++count;
            }

            while(edges < m) {
                for(int i = 0; i < n; i++) {
                    if(v[i].size() == D)
                        continue;
                    for(int j = 0; j < n; j++) {
                        if(v[i].find(j) == v[i].end()) {
                            v[i].insert(j);
                            ++edges;
                            break;
                        }
                        if(edges == m)
                            break;
                    }
                    if(edges == m)
                        break;
                }
            }
            for(int i = 0; i < n; i++) {
                set <int>::iterator it = v[i].begin();
                for(; it != v[i].end(); ++it) {
                    printf("%d %d\n", i+1, (*it)+1);
                }
            }
        }
    }
    return 0;
}

我不知道这段代码是否正确。