URAL 1022. Genealogical Tree

7 篇文章 2 订阅


     

本来是写的DFS求最长路的,结果WA at test #2 ,后来发现是因为 图不一定要是连通图。然后就好麻烦了……写了个多次的DFS,没过。

写了个先连成连通图 ,再一次DFS,结果连接成连通图的过程中有错误,WA at  test #5 。


最后发现这题是求 拓扑排序,从头写起,终于过了。

每次删除入度最小的顶点,并输出这个顶点的编号。我写的有点复杂……

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#define FOR(i,n) for(long long (i)=1;(i)<=(n);(i)++)
#define For(i,n) for(long long (i)=0;(i)<(n);(i)++)
using namespace std;
struct ArcNode{
	int from,to;
	ArcNode *nextOut;//出边表 
	ArcNode *nextIn;//入边表 
};
struct Node{
	ArcNode *In;
	ArcNode *Out;
	int K;//入度
	int vis;//0表示已经被删掉。
	Node():In(NULL),Out(NULL),K(0),vis(0){}
	bool operator <(const Node &B)const{
		return K<B.K; 
	} 
}node[101];
void Arc(int from,int to){//建边
	ArcNode *temp=new(ArcNode);
	temp->from=from;temp->to=to;
	//接进入边表 
	temp->nextIn=node[to].In;node[to].In=temp;node[to].K++;
	//接进出边表
	temp->nextOut=node[from].Out;node[from].Out=temp;
}
void DeleNode(int i){//删节点
	//删除出边 
	while(node[i].Out){
		ArcNode *temp=node[i].Out;
		node[i].Out=node[i].Out->nextOut;
		node[temp->to].K--;
			//删除to节点的入边;
			if(node[temp->to].In==temp){
				node[temp->to].In=temp->nextIn;
			}
			else{
				ArcNode *temp2=node[temp->to].In;
				while(temp2){
					if(temp2->nextIn==temp){
						temp2->nextIn=temp->nextIn;
						break;
					}
					temp2=temp2->nextIn;
				}
			}
		delete temp;
	}
	//删除入边
	while(node[i].In){
		ArcNode *temp=node[i].In;
		node[i].In=node[i].In->nextIn;
		node[i].K--;
			//删除from节点的出边;
			if(node[temp->from].Out==temp){
				node[temp->from].Out=temp->nextOut;
			}
			else{
				ArcNode *temp2=node[temp->from].Out;
				while(temp2){
					if(temp2->nextOut==temp){
						temp2->nextOut=temp->nextOut;
						break;
					}
					temp2=temp2->nextOut;
				}
			}
		delete temp;
	}
}
struct A{
	int i;
	int K;
	bool operator<(const A&B)const{
		return K <B.K; 
	}
}AA[101];
int N;
int main(void)
{
	while(cin>>N){
		FOR(i,N) node[i].K=0,node[i].vis=1;
		//建边 
		FOR(i,N){
			int a;
			scanf("%d",&a);
			while(a) {
				Arc(i,a);
				scanf("%d",&a);
			}
		}
		 //计算
		int ALL=N;
		while(ALL>0){
			for(int i=1;i<=N;i++){
				AA[i].i=i;AA[i].K=node[i].K;
			}
			sort(AA+1,AA+N+1);//排序找到入度最小的边 
			int Cur=1;
			while(!node[AA[Cur].i].vis) Cur++; 
			DeleNode(AA[Cur].i);node[AA[Cur].i].vis=0;
			ALL--;
			if(ALL) printf("%d ",AA[Cur].i);
			else printf("%d\n",AA[Cur].i);
		}
	}
return 0;
}










评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值