Petri网导论这本教材第三章的算法
C++实现
输入 为 库所和变迁个数 以及关联矩阵
4 4
1 -1 0 0
-1 1 1 0
1 0 -1 -1
0 -1 -1 1
1 0 0 0
3 4
-1 1 0
1 -1 0
0 1 -1
0 -1 1
0 1 0
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <sstream>
#include <queue>
#include <utility>
using namespace std;
#define LL long long
#define ULL unsigned long long
#define inf 0x7fffffff
#define mod %100000007
#define mp make_pair
#define fi first
#define se second
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define mid int m=(l+r)>>1
using namespace std;
const int nmax = 1000 + 10;
const int tmax = 100 + 10;
const int pmax = 100 + 10;
int np, nt;//输入库所和变迁个数
int A[tmax][pmax];//输入关联矩阵
int A1[tmax][pmax], A2[tmax][pmax];//输出矩阵A+ 和输入矩阵A-
int M0[pmax];//输入初始标识
int M[pmax], M1[pmax];//当前标识
struct Node {//CT节点
int m[pmax];//标识向量
struct Node* parent;//指向父节点的指针
int t;//变迁编号 1,2……,nt(对应下标+1)
int flag;//标记 0为新,1为旧,-1为端点
Node() {
memset(m, 0 ,sizeof(m));
parent = NULL;
t = 0;
flag = 0;
};
} Tr[nmax];
bool repeat(int i) {//true为M是重复节点
for(int j = 0; j < np; ++j) {
if(M[j] != Tr[i].m[j]) return false;
}
return true;//M(j) == m[j] j=1,2,...,np
}
bool check(int i) {// true为ti可发生
for(int j = 0; j < np; ++j) {
if(M[j] < A2[i][j]) return false;
}
return true;//M[ti> 充要条件:M(j)>=aij j=1,2,...,np
}
int main() {
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
int cases = 0;
/* 输入库所个数np和变迁个数nt,0 0结束输入 */
while(~scanf("%d %d", &np, &nt) && (np != 0 || nt != 0)) {
printf("Case %d:\n", ++cases);
int CR = 0;//1为可覆盖树,0为可达树
int k = 0;//记录CT中节点的个数
/* 清理上一组数据 */
memset(Tr, 0, sizeof(Tr));
memset(A, 0, sizeof(A));
memset(A1, 0, sizeof(A1));
memset(A2, 0, sizeof(A2));
memset(M0, 0, sizeof(M0));
memset(M, 0, sizeof(M));
memset(M1, 0, sizeof(M1));
/* 输入关联矩阵A和初始标识M0 */
for(int i = 0; i < nt; ++i) {
for(int j = 0; j < np; ++j) {
scanf("%d", &A[i][j]);
if(A[i][j] == 1) A1[i][j] = A[i][j];
if(A[i][j] == -1) A2[i][j] = -A[i][j];
}
}//关联矩阵
/* step0 以初始标识为CT的根节点,并标为新=0 */
Node *head;//空的头节点
head = (Node*)malloc(sizeof(struct Node));
head->parent = NULL;
Tr[k].parent = head;//根节点(初始标识)M0=Tr[0] 指向空的头节点head
for(int i = 0; i < np; ++i) {
scanf("%d", &M0[i]);
Tr[k].m[i] = M0[i];//Tr[0]为CT根节点
}//初始标识
k++;//目前只有一个根节点k=1
/* step1 是否存在新=0的节点,任选一个新的节点为当前节点=M */
while(1) {
int nnew = -1;//当前节点(标识)的下标
for(int i = 0; i < k; ++i) {
if(Tr[i].flag == 0) {
nnew = i;//有新节点,下标为i
break;
}
}if(nnew == -1) {//判断没有新的节点,结束while
break;
}//step1 结束,否则继续
/* 将任意一个新节点设置为当前节点=M */
for(int i = 0; i < np; ++i) {
M[i] = Tr[nnew].m[i];
}
/* step2 根节点=head 到 当前节点=M 的路径上 如果有重复标为旧flag=1 */
int rep = 0;
Node *q = Tr[nnew].parent;//q指向当前节点M的父节点
while(q->parent != NULL) {
int f = 0;
for(int j = 0; j < np; ++j) {
if(M[j] != q->m[j]) f = 1;
}if(f == 0) {//M是重复节点
Tr[nnew].flag = 1;//标为旧=1
rep = 1;
break;
}
q = q->parent;
}if(rep == 1) {
continue;//返回while,step1
}//step2 结束,不标为旧则继续
/* step3 当前节点=M 如果所有的变迁都是死的标为端点=-1 */
int dead = -1;
for(int i = 0; i < nt; ++i) {
if(check(i)) {//存在可发生的变迁ti
dead = i;
break;
}
}if(dead == -1) {
Tr[nnew].flag = -1;//所有的变迁都不可发生,标为端点=-1
continue;//返回while,step1
}//step3 结束,不标为端点则继续
/* step4 对每个可发生的t */
for(int i = 0; i < nt; ++i) {//遍历每一个变迁t
if(check(i)){//ti可发生
for(int j = 0; j < np; ++j) {
/* 计算M1 */
if(M[j] == 'w') M1[j] = M[j];
else M1[j] = M[j] + A[i][j];
Tr[k].m[j] = M1[j];
}
/* 插入w分量 */
Node *p = &Tr[nnew];//p指向当前节点M
while(p->parent != NULL) {
int f = 0;
for(int j = 0; j < np; ++j) {
if(p->m[j] > M1[j]) {
f = -1;//不满足条件
break;
}
}if(f == 0) {
for(int j = 0; j < np; ++j) {
if(p->m[j] < M1[j]) {
Tr[k].m[j] = 'w';
CR = 1;//存在w分量
}
}
}
p = p->parent;
}//判断是否有无穷w
/* 插入新节点 */
Tr[k].parent = &Tr[nnew];//有向弧
Tr[k].t = i + 1;//有向弧旁标
Tr[nnew].flag = 2;//抹去标注
k++;//节点个数增加
}
}//step4 结束,创建了新节点,继续找标为新=1的节点
}//无标为新的节点,while结束
/* step1 结束,算法结束 */
/* 输出得到可覆盖树CT或者可达树RT */
if(CR == 0) printf("The tree is reachability tree ");
else printf("The tree is coverability tree ");
printf("of %d nodes.\n", k);
for(int i = 0; i < k; ++i) {
for(int j = 0; j < np; ++j) {
if(j == 0) printf("M%d = [", i);
if(Tr[i].m[j] != 'w') printf("%d", Tr[i].m[j]);
else printf("%c", Tr[i].m[j]);
if(j != np - 1) printf(",");
else printf("]");
}
if(Tr[i].t != 0) printf(" t%d", Tr[i].t);
if(Tr[i].parent != head) {
for(int j = 0; j < np; ++j) {
if(j == 0) printf(" parent = [");
if(Tr[i].parent->m[j] != 'w') printf("%d", Tr[i].parent->m[j]);
else printf("%c", Tr[i].parent->m[j]);
if(j != np - 1) printf(",");
else printf("]");
}
}
printf("\n");
}
printf("\n");
}
return 0;
}
16年12月完成 现在只是存一下(主要比较好找)