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月完成 現在只是存一下(主要比較好找)