Elegant Construction HDU-5813 构造

来源:互联网 发布:知乎账号购买 编辑:程序博客网 时间:2024/05/16 01:31

- 题意

    给出我们从1-n城市的点能直接(或间接)到达的城市的数量作为这个点的权值 让我们判断并构造一个单向图 使得这个图完全契合给出的数据 special judge 任意一组结果就可以    题目中给出 图中无环无回路

- 分析

刚看到根据联通数目构造图 哇 这怎么做 好复杂啊!这该如何构造??其实想一下就可以发现 题目中说是一个无环图 也就是说 

任何一个有向无环图中必定至少存在一个入度为0的顶点,至少存在一个出度为0的顶点,否则图中必存在环。有向无环图对于构造一个任务必须发生在另一个任务之前的这种依赖模型特别有效。有向无环图的另一个应用是规划项目,例如建造房屋时,框架的设计必须在盖屋顶之前。

否则 如果无环图中的每一个点都有出度的话 这与无环的性质矛盾我们说 一个无环图就是一个可以被拓补排序的图 也就说 这个图 一定可以被拓扑排序所以我们发现低权值的点 不会连向高权值的点 因为一个低权值的点 如果连向一个比自己权值高的点就会产生矛盾 所以当我们把低权值的点处理完后 把每一层低权值的点处理完后 相应的高一层的点就相当于单个点 就像拓扑排序 因为高一层的点来自低一层的点 所以我们从低到高处理 每处理完一层点比其只高一层的点 就相当于单个点 就像是拓扑排序的步骤每排好一个点 就把这个点的出度全部删除 这里同理每选完一个点 就把这个点 直接到达的点看成 无入度点 所以就可以一个个选了 生序排序 从低到高处理 相当于反向拓扑排序的步骤 如果这个处理的这个点 找不到足够的点 可以连就输出NO 证明一个有向图是有向无环图方法: 拓扑排序方法

code

#include<bits/stdc++.h>using namespace std;vector<int>v[1010];struct node{    int o,val;}a[1010];bool cmp(node aa,node bb){    return aa.val<bb.val;}int main(){    int p,t,n;    scanf("%d",&t);    for( p=1;p<=t;p++){        scanf("%d",&n);        for(int i=1;i<=n;i++){            scanf("%d",&a[i].val);            a[i].o = i;        }        printf("Case #%d: ",p);        sort(a+1,a+1+n,cmp);        if(a[1].val!=0){            puts("No");            continue;        }        int i,c=0,j;        bool f=0;        for(i=1;i<=n;i++)        {            if(a[i].val==0)continue;            for(j=1;j<i&&j<=a[i].val;j++){                v[a[i].o].push_back(a[j].o);                c++;            }            if(v[a[i].o].size()!=a[i].val){f=1;break;}        }        if(f)puts("No");        else{            puts("Yes");            printf("%d\n",c);            for(int i=1;i<=n;i++)                for(int j=0;j<v[i].size();j++)                    printf("%d %d\n",i,v[i][j]);        }        for(int i=1;i<=n;i++)v[i].clear();    }    return 0;}
原创粉丝点击