标签:sgu
题目大意:
在系统学中,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; }
标签:sgu
原文地址:http://blog.csdn.net/qq_21995319/article/details/42782015