• POJ 3687 Labeling Balls


    http://poj.org/problem?id=3687

    题意:

    有n个小球,权重分别为1~n。现在要为这些小球贴上1~n的标签,规则是标签1所对应的小球的权重应尽量小,其次是标签2...接下来会有m个要求,就是标签a所贴小球的权重必须小于标签b所贴小球的权重。

    思路:

    拓扑排序。

    首先我考虑的是正向的拓扑排序,建好图后每次选择度数为0的最小的顶点,为它贴上当前权重最小的小球。但是这样做有缺陷,举个例子来说:

    5 3
    1 4
    4 2
    3 5
    正确答案应该是输出1 3 4 2 5,但是如果按照我的做法去做的话,输出的是1 4 2 3 5。因为2在4后面,先处理了3,这样导致了标签2所贴球的权重较大,最优的是先处理4,这样2就能有较小值。
    于是考虑用反向拓扑来做,每次将小的那端的度数+1,每次选择度数为0的最大的顶点,为它贴上当前权重最大的小球。这样就保证了大标签贴在了权重大的球上。
     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 using namespace std;
     6 
     7 const int maxn = 200 + 5;
     8 
     9 int n, m;
    10 int g[maxn][maxn];
    11 int indegree[maxn];
    12 int ans[maxn];
    13 
    14 int tuopu()
    15 {
    16     int cnt = n;
    17     for (int i = 1; i <= n; i++)
    18     {
    19         int num = 0, loc;
    20         for (int j = 1; j <=n;j++)
    21         {
    22             if (indegree[j] == 0)
    23             {
    24                 num++;
    25                 loc = j;
    26             }
    27         }
    28         if (num == 0)     return -1;
    29         ans[loc] = cnt--;
    30         indegree[loc] = -1;
    31         for (int j = 1; j <= n;j++)
    32         if (g[loc][j])   indegree[j]--;
    33     }
    34     return 1;
    35 }
    36 
    37 int main()
    38 {
    39     //freopen("D:\txt.txt", "r", stdin);
    40     int T;
    41     int x, y;
    42     scanf("%d", &T);
    43     while (T--)
    44     {
    45         memset(g, 0, sizeof(g));
    46         memset(indegree, 0, sizeof(indegree));
    47         memset(ans, 0, sizeof(ans));
    48         bool flag = true;
    49         scanf("%d%d", &n, &m);
    50         while (m--)
    51         {
    52             scanf("%d%d", &x, &y);
    53             if (x == y)  flag = false;
    54             //反向拓扑
    55             if (!g[y][x])     //这里需要注意一下重边的问题
    56             {
    57                 g[y][x] = 1;
    58                 indegree[x]++;
    59             }
    60         }
    61         if (flag)
    62         {
    63             int p = tuopu();
    64             if (p == -1)     printf("-1
    ");
    65             else
    66             {
    67                 for (int i = 1; i < n; i++)
    68                     cout << ans[i] << " ";
    69                 cout << ans[n] << endl;
    70             }
    71         }
    72         else printf("-1
    ");
    73     }
    74     return 0;
    75 }
     
  • 相关阅读:
    类似Sina新浪滑动门代码
    纯CSS无JS实现灰色下拉导航菜单代码
    滑动门与选项卡互转的实现方法代码
    一款横向、竖向两个选项卡Tab一起联动的导航代码
    C#Brush的使用(转载)
    泛型学习笔记(转载)
    Application之间共享MasterPage(转载)
    ReportView学习笔记一(转载)
    BackGroundWorker学习
    加下划线的TextBox
  • 原文地址:https://www.cnblogs.com/zyb993963526/p/6652308.html
Copyright © 2020-2023  润新知