Elegant Construction---hdu5813(构造图)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5813

题意是:有n个点,每个点都能到达num个点,让我们构造任意一个有向图满足条件,即:使得 i 能到达 a[i] 个点;

将顶点按能到达的点数从小到大排序,排好序之后每个点只能往前面的点连边. 所以我们必须要让前面点的个数大于或等于它要连得点的个数;

因而如果存在一个排在第i位的点(前面有i-1个点),i-1>=要求到达的点数(i>要求到达的点数);

按照上述方法构造出图. 复杂度O(N^2).

#include <cstring>
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
using namespace std;
#define N 1005
#define met(a, b) memset(a, b, sizeof(a))

typedef long long LL;

struct node
{
    int Id, num;
    friend bool operator < (node p, node q)
    {
        return p.num < q.num;
    }
}a[N];

int u[N*N], v[N*N];

int main()
{
    int T, t = 1, n;
    scanf("%d", &T);
    while(T--)
    {
        scanf("%d", &n);

        for(int i=1; i<=n; i++)
        {
            scanf("%d", &a[i].num);
            a[i].Id = i;
        }
        sort(a+1, a+n+1);

        int k = 0, flag = 0;

        for(int i=n; i>=1; i--)
        {
            if(a[i].num >= i)///前面点的个数必须要大于它要到达的点的个数;
            {
                flag = 1;
                break;
            }
            for(int j=1; j<=a[i].num; j++)///由于只需输出一组符合条件的解即可,所以我们可以用a[i].Id连接num条任意的a[j].Id(j < i);
            {
                u[k] = a[i].Id;
                v[k++] = a[j].Id;
            }
        }
        if(flag)
            printf("Case #%d: No
", t++);
        else
        {
            printf("Case #%d: Yes
", t++);

            printf("%d
", k);
            for(int i=0; i<k; i++)
                printf("%d %d
", u[i], v[i]);
        }
    }
    return 0;
}
/*
3
3
2 1 0
2
1 1
4
3 1 1 0
*/
View Code
原文地址:https://www.cnblogs.com/zhengguiping--9876/p/5755952.html