POJ 3687 Labeling Balls (拓扑排序)

题意:给定m个球的关系,求出具有最小字典序的各个球的重量。

思路:拓扑排序,但是不能建正向图,只能建反向图,具体解释见Answeror牛:

  http://www.answeror.com/archives/23913

PS:图论中的技巧太多,只靠做题感觉是亡羊补牢,只有把理论知识搞透彻,才能真正明白各个题中隐藏的数学原理,向这样正向和反向图中的细微区别也就yin不了人了...

#include <iostream>
#include
<cstdio>
#include
<algorithm>
#include
<memory.h>
#include
<cmath>
#include
<bitset>
#include
<queue>
#include
<vector>
using namespace std;

const int BORDER = (1<<20)-1;
const int MAXSIZE = 37;
const int MAXN = 205;
const int INF = 1000000000;
#define CLR(x,y) memset(x,y,sizeof(x))
#define ADD(x) x=((x+1)&BORDER)
#define IN(x) scanf("%d",&x)
#define OUT(x) printf("%d\n",x)
#define MIN(m,v) (m)<(v)?(m):(v)
#define MAX(m,v) (m)>(v)?(m):(v)
#define ABS(x) ((x)>0?(x):-(x))

typedef
struct{
int v;
int next;
}Edge;

int index,n,m;
Edge edge[MAXN
*MAXN];
int weight[MAXN],grad[MAXN],net[MAXN];
bool g[MAXN][MAXN],visit[MAXN];

void add_edge(const int& u,const int& v)
{
edge[index].v
= v;
edge[index].next
= net[u];
net[u]
= index++;
}
int init()
{
index
= 0;
CLR(visit,
0);
CLR(net,
-1);
CLR(grad,
0);
CLR(g,
0);
return 0;
}
int input()
{
int i,j,a,b;
scanf(
"%d%d",&n,&m);
for(i = 0; i < m; ++i)
{
scanf(
"%d %d",&a,&b);
if(!g[b][a])//判重
{
g[b][a]
= true;
add_edge(b,a);
//反向图
++grad[a];
}
}
return 0;
}
int work()
{
int i,j,tmp,mmin;
for(i = 0; i < n; ++i)//拓扑
{
for(j = n; j > 0 && grad[j]!=0; --j)
;
if(j <= 0)
{
printf(
"-1\n");
return 0;
}
grad[j]
= -1;
weight[j]
= n-i;
for(j = net[j]; j != -1; j = edge[j].next)
--grad[edge[j].v];
}
printf(
"%d",weight[1]);
for(i = 2; i <= n; ++i)
printf(
" %d",weight[i]);
printf(
"\n");
return 0;
}
int main()
{
int t ;
IN(t);
while(t--)
{
init();
input();
work();
}
return 0;
}
原文地址:https://www.cnblogs.com/lvpengms/p/1719200.html