HDU_2647 Reward (拓扑排序)

注意将后一个数插到前一个数上,然后用队列每次存储入度为0的数,累加同一工资级别的人的工资

View Code
#include <stdio.h>
#include
<stdlib.h>
#include
<string.h>
#define N 10005
typedef
struct node //邻接表节点
{
int adj; //节点值
struct node * next;
}node;
struct //顶点
{
int in; //入度
node * next;
}v[N];

int visited[N], queue[N], front, rear;

void insert(int x, int y) //尾插法将y指向x
{
node
* p = (node *)malloc(sizeof(node));
p
->adj = x;
p
->next = v[y].next;
v[y].next
= p;
v[x].
in++; //x的入度增加
}

void topo(int x) //清空队列中存的入度为0的数
{
if(v[x].next == NULL)
return;
node
* p = v[x].next;
while(p)
{
v[p
->adj].in--; //x点指向的点的入度--
p = p->next; //指向邻接表的下一个节点
}
v[x].next
= NULL; //将v[x]节点指向空,表示与x之间存在弧的点都已经清空
}

int main()
{
int n, m;
while(scanf("%d%d", &n, &m)!=EOF)
{
rear
= front = 0; //队头队尾置0
memset(visited, 0, sizeof(visited));
memset(v,
0 , sizeof(v));
int sum = 0, flag = 0, base = 888;
int i, j, a, b, sign;
for(i = 0; i < m; i++)
{
scanf(
"%d%d", &a, &b);
insert(a, b);
//将a插到b的表上,即使b指向a
}
for(j = 0; j < n;)
{
sign
= 0;
for(i = 1; i <= n; i++)
{
if(v[i].in == 0 && !visited[i])
{
visited[i]
= 1; //标记i点已遍历过
sign = 1; //标记,如果sign = 0 说明没有入度为0的点即存在回路
queue[rear++] = i;//将入度为0的数存入队列
}
}
if(!sign)
{
flag
= 1;
break;
}
while(front < rear) //遍历队列内的元素,并求出sum
{
topo(queue[front
++]); //从队列头开始往后找
j++; //统计已经遍历过的节点数
sum += base; //求和
}
base++;
}
if(flag) printf("-1\n");
else printf("%d\n", sum);
}
return 0;
}
posted @ 2011-07-30 16:42  AC_Von  阅读(297)  评论(0编辑  收藏  举报