编译原理 子集构造法实现

输入说明

第一行 点数n 边数m 集合中字符数目k

第二行 集合中的字符

接下去m行 每一行三个值 起点 终点 经过的边上的字符


输出:

构造好的边

新构造节点包含的原先的点的集合


#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <stack>
#include <queue>
#include <string>
#include <vector>
#include <set>
#include <map>
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define sz(x) ((int)(x).size())
#define fi first
#define se second
using namespace std;
typedef vector<int> vi;
const int N = 1000;
int n,m,k;
struct Edge{
    int to,nxt;
    char w;
};
class Graph{
    private:
        int *head;
        int tot;
        Edge *edge;
        vector<vi> ans;
        bool *vis;
        queue<vi> que;
        vector<char> chArray;
        int n,m;
    public :
        void init(int _n,int _m){
            n=_n;m=_m;
            cout<<n<<" "<<m<<endl;
            head=(int*)malloc(sizeof(int)*(n));
            for(int i=0;i<n;i++) head[i]=-1;
            edge=(Edge*)malloc(sizeof (Edge)*(m*2));
            vis=(bool*)malloc(sizeof(bool)*n);
            tot=0;
            chArray.clear();
            ans.clear();
        }
        void addEdge(int u,int v,char w){
            edge[tot].w=w;
            edge[tot].to=v;
            edge[tot].nxt=head[u];
            head[u]=tot++;
        }
        void addCh(char ch){
           chArray.pb(ch);
        }
        bool _same(vi a,vi b){
            if(a.size()!=b.size()) return false;
            sort(all(a));
            sort(all(b));
            for(int i=0;i<a.size();i++) if(a[i]!=b[i]) return false;
            return true;
        }
       int find_pos(vi a){
            for(int i=0;i<ans.size();i++) if(_same(ans[i],a)) return i;
            return ans.size();
        }
        void print_vi(vi v){
            for(int i=0;i<v.size();i++) cout<<v[i]<<" ";
            cout<<endl;
        }
        void subset_construction(int start,int en){
            while(que.size()) que.pop();
            vi _tmp;
            _tmp.pb(start);
            vi tmp=find_ch_path(_tmp,'e');
            que.push(tmp);
            ans.pb(tmp);
            while(!que.empty()){
                vi now=que.front();
                que.pop();
                for(int i=0;i<chArray.size();i++){
                    int w=chArray[i];
                    vi tmp=find_ch_path(now,w);
                    tmp=find_ch_path(tmp,'e');
                    int pos=find_pos(tmp);
                    if(pos>=ans.size()) {
                        ans.pb(tmp);
                        que.push(tmp);
                    }
                    int from=find_pos(now);
                    if(from!=pos)
                    cout<<from<<" "<<pos<<" "<<(char)w<<endl;
                }
            }
        }
        void print(){
            cout<<"the whole num: "<<ans.size()<<endl;
            for(int i=0;i<ans.size();i++){
                cout<<i<<": ";
                sort(all(ans[i]));
                for(int j=0;j<ans[i].size();j++) cout<<ans[i][j]<<" ";
                cout<<endl;
            }
        }
        vi find_ch_path(vi&in,char w){
            for(int i=0;i<n;i++) vis[i]=false;
            vi ret;
            ret.clear();
            for(int i=0;i<in.size();i++) {
                ret.pb(in[i]);
                vis[in[i]]=true;
            }
            for(int i=0;i<in.size();i++) {
                dfs(in[i],ret,w);
            }
            return ret;
        }
        void dfs(int u,vi& ret,char ch){
            for(int k=head[u];~k;k=edge[k].nxt){
                int v=edge[k].to;
                char w=edge[k].w;
                if(vis[v] || w!=ch) continue;
                 vis[v]=true;
                 ret.pb(v);
                dfs(v,ret,ch);
            }
        }
}G;

int main()
{
freopen("aaa","r",stdin);
    cin>>n>>m>>k;
    G.init(n,m);
    for(int i=0;i<k;i++){
        char ch;
        cin>>ch;
        G.addCh(ch);
    }
    for(int i=1;i<=m;i++){
        int u,v;char ch;
        cin>>u>>v>>ch;
        G.addEdge(u,v,ch);
    }
    G.subset_construction(0,n-1);
    G.print();
    return 0;
}

输入例子

15 18 2
a b
0 1 e
1 2 e
1 4 e
2 3 a
4 5 b
3 6 e
5 6 e
6 7 e
6 1 e
0 7 e
7 8 a
8 9 e
8 11 e
9 10 a
11 12 b
10 13 e
12 13 e
13 14 e



你可能感兴趣的:(编译原理 子集构造法实现)