sgu-219 ynchrograph

题目大意:

在系统学中,Petri nets的一种特殊情况经常被纳入考虑范围,这种特殊情况被称为Synchrograph。Synchrograph是一个有向图,每条弧都有一个非负整数权。一个点,如果所有指向它的边都是正数(也就是大于0),这个点就称之为“可燃点”。 

对Synchrograph的操作是一轮一轮进行的。在每一轮中,操作者都会随机的选一个“可燃点”进行“燃烧”。所谓燃烧就是:所有指向这个点的弧权都减1,所有从这个点指出去的弧都加1。每一轮之后,“可燃点”根据新的弧权被更新,然后下一轮操作继续进行。 
如果存在一个操作序列,使得某个点变成可燃点,那么这个点就称之为“潜在活动点”。 

如果经过任意一个操作序列之后,某个点依然是“潜在活动点”,这个点就称之为“活动点”。 

给你一个有向图,然后要你求出哪些是活动点(1),哪些是非活动点(0)



解题思路:

由于本人太弱,所以讲不清楚,直接指条明路吧:http://wenku.baidu.com/view/fe3dc1bf1a37f111f1855b5d

我也是看完了才会做的。


AC代码:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
#define MAX(a,b) ((a)>(b)?(a):(b))
#define MIN(a,b) ((a)>(b)?(b):(a))

using namespace std;
int n,m;
struct bian_
{
	int num;
	int elc;
	int next;
}bian[50010]={{0,0,0}};
int First[1010]={0};

void Add(int p,int q,int r,int k)
{
	bian[k].num=q;
	bian[k].elc=r;
	bian[k].next=First[p];
	First[p]=k;
	return;
}

int du[1010]={0};
int dui[1010]={0};
int duip=0;
int ans[1010]={0};

void dfs(int k)
{
	for(int p=First[k];p!=0;p=bian[p].next)
	{
		if(ans[bian[p].num]==1) continue;
		ans[bian[p].num]=1;
		dfs(bian[p].num);
	}
	return;
}

int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++)
	{
		int p,q,r;
		scanf("%d%d%d",&p,&q,&r);
		Add(p,q,r,i);
		if(r==0) du[q]++;
	}
	
	for(int i=1;i<=n;i++)
		if(du[i]==0)
			dui[++duip]=i;
	
	for(int i=1;i<=duip;i++)
	{
		for(int p=First[dui[i]];p!=0;p=bian[p].next)
		{
			if(bian[p].elc!=0) continue;
			du[bian[p].num]--;
			if(du[bian[p].num]==0)
				dui[++duip]=bian[p].num;
		}
		dui[i]=0;
	}
	
	for(int i=1;i<=n;i++)
		if(du[i]!=0 && ans[i]==0)
			dfs(i);
	
	for(int i=1;i<=n;i++)
		printf("%d\n",ans[i]^1);
	
	return 0; 
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值