POJ 3687 逆序拓扑

额。题目大意:有N个球。编号和重量都是唯一不重复的。然后。给你m个pair a和b,表示编号为a的点一定比编号为b的点轻。然后捏、输出每个点对应的重量。关键是要求。如果有多种可能性的话,输出让序号小的点重量也尽量小的ans....而且先满足1号。再二号。and so on....那么问题来了。如果我们按照编号从小到大开始拓扑、然后每次对编号小的球赋给当前最小重量的话。T_T。貌似无法保证所有的球从小到大开始编号小则重量尽量小、比如说、第一次 入度为0得点有3 4 5 那么赋给了3重量1.第二次入度为0的点有2 4 5.那么。只能赋给2重量2了。如果再下次是4  5的话、赋给4 号球 重量3、再下次是1 5.赋给1号球重量4.但实际上这说明4——>1、而3 4 5 是并列关系。那就是先满足4的话就可以让1号球最小喽。恩。。是这样滴、、、

代码也灰常简单。就是按照入度为0的点的顺序来。貌似这就是拓扑排序。。2333333333333好吧。。我是很无知地。。。以为拓扑排序一定会用到邻接表形式。加一条边的insert函数。、T_T

附代码:
#include<stdio.h>
#include<string.h>
#include<iostream>
#define maxn 210
#define maxm 41000
using namespace std;

int digree[maxn];
int map[maxn][maxn];
int ans[maxn];
int vis[maxn];
int n, m;

void init()
{
    memset(digree, 0, sizeof(digree));
    memset(map, 0, sizeof(map));
    memset(vis, 0, sizeof(vis));
}

void topsort()
{
     for (int i=n; i>=1; --i)
     {
         int k = -1;
         for (int j=n-1; j>=0; --j)
         {
             if (!vis[j] && digree[j] == 0)
             {
                 k = j;
                 break;
             }
         }
         if (k == -1)
         {
             cout << "-1 ";
             return;
         }
         vis[k] = 1;
         ans[k] = i;
         for (int j=0; j<n; ++j)
         {
             if (map[k][j])
             digree[j]--;
         }
     }
     cout << ans[0];
     for (int i=1; i<n; ++i)
     {
        cout << ' ' << ans[i];
     }
     cout << endl;
}

int main()
{
    int t;
    cin >> t;
    while(t--)
    {
        cin >> n >> m;
        init();
        for (int i=0; i<m; ++i)
        {
            int a, b;
            cin >> a >> b;
            a--; b--;
            if (!map[b][a])
            {
               map[b][a] = 1;
               digree[a]++;
            }
        }
        topsort();
    }
    return 0;
}

原文地址:https://www.cnblogs.com/icode-girl/p/4552773.html