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 ;
}

 

 

你可能感兴趣的:(label)