• HDU 5813 Elegant Construction ——(拓扑排序,构造)


      可以直接见这个博客:http://blog.csdn.net/black_miracle/article/details/52164974

      对其中的几点作一些解释:

      1.这个方法我们对队列中取出的元素,把仍有出度的点连接到这个点时,这个点是不会连接到多余的点的,因为:一个点出队列的时候其他没入队的点都已经连接到这个点过了,后来再一个点出队列的时候,我们拿此时没入队的点连接到它时,肯定已经连接过之前的点了,所以肯定不会增加到达的点数。(可能我也用语言讲不太清楚233。。。)

      2.为什么这个人的博客说最终如果num不是0的话就表示成环了?理由如下:不妨考虑四个点的情况:3,3,3,0。最后一个点操作后,出度变为2,2,2,0。这个时候队列已经空了,然而num还不是0,说明还有点没有完成达到它所需要达到的点数(也可以这么解释:num的个数表示还没有完成点数个数任务的点的个数,num=0才表示所有的点都已经完成到达点数个数的目标了,不是0当然不能够满足题意了)。至于为什么是成环的话,因为它们不能够完成点数个数任务,所以他们必须连向别人构成环来构成目标了呗~

      反正这个拓扑排序有点奥义,需要好好理解~

      代码如下:

     1 #include <stdio.h>
     2 #include <algorithm>
     3 #include <string.h>
     4 #include <vector>
     5 #include <set>
     6 #include <queue>
     7 using namespace std;
     8 const int N = 1000 + 5;
     9 
    10 struct edge
    11 {
    12     int u,v;
    13     bool operator < (const edge &temp) const
    14     {
    15         return u == temp.u ? v<temp.v : u<temp.u;
    16     }
    17 };
    18 int a[N],inq[N],n;
    19 set<edge> S;
    20 
    21 void solve()
    22 {
    23     queue<int> Q;
    24     int cnt = n;
    25     for(int i=1;i<=n;i++)
    26     {
    27         if(!a[i])
    28         {
    29             Q.push(i);
    30             inq[i] = 1;
    31             cnt--;
    32         }
    33     }
    34     while(!Q.empty())
    35     {
    36         int x = Q.front();Q.pop();
    37         for(int i=1;i<=n;i++)
    38         {
    39             if(!inq[i])
    40             {
    41                 a[i]--;
    42                 S.insert((edge){i,x});
    43                 if(!a[i])
    44                 {
    45                     Q.push(i);
    46                     inq[i] = 1;
    47                     cnt--;
    48                 }
    49             }
    50         }
    51     }
    52     if(cnt) puts("No");
    53     else
    54     {
    55         puts("Yes");
    56         printf("%d
    ",S.size());
    57         for(set<edge>::iterator it=S.begin();it!=S.end();it++)
    58         {
    59             edge e = *it;
    60             printf("%d %d
    ",e.u,e.v);
    61         }
    62     }
    63 }
    64 
    65 int main()
    66 {
    67     int T;scanf("%d",&T);
    68     for(int kase=1;kase<=T;kase++)
    69     {
    70         scanf("%d",&n);
    71         S.clear();memset(inq,0,sizeof(inq));
    72         for(int i=1;i<=n;i++) scanf("%d",a+i);
    73         printf("Case #%d: ",kase);
    74         solve();
    75     }
    76     return 0;
    77 }
  • 相关阅读:
    JQuery的摸索之路(一)
    C#操作excel(NPOI篇)
    Mschart学习(MSchart介绍)
    JQuery的摸索之路(二比较)
    Mschart学习(开篇)
    Mschart学习(官方demo共享)
    SQL进阶提升(疑惑篇order by)学习sql server2005 step by step(十一)
    一步一步学习C#(二C#基础)
    NickLee的学习
    Linux 命令学习一
  • 原文地址:https://www.cnblogs.com/zzyDS/p/5793648.html
Copyright © 2020-2023  润新知