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 }
原文地址:https://www.cnblogs.com/zzyDS/p/5793648.html