#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<map>
#include<queue>
using namespace std;
//基类
class Graph{
protected:
int n_v;//顶点数量
bool directed;//有向的
vector<string>vertices;//顶点名字
map<string,int>iov;//log(n) 顶点名字->(映射)顶点的编号
vector<bool> visited;
virtual void dfs(int v)=0;
public:
Graph(bool dir=false){//传过来的话就不用默认(空图,无向)了
directed=dir;
n_v=0;
}
//重载
Graph(vector<string>v,bool dir=false){
directed=dir;
n_v=(int)v.size();
vertices=v;
for(int i=0;i<n_v;i++){
iov[vertices[i]]=i;
}
}
Graph(int n,bool dir=false){
directed=dir;
n_v=n;
vertices.resize(n);
int i;
for(i=0;i<n;i++){
vertices[i]=to_string(i);
iov[to_string(i)]=i;
}
}
virtual void print()=0;
virtual void insertV(){
insertV(to_string(n_v));
}
virtual bool insertV(string v){
if(iov.find(v)!=iov.end()) return false;
vertices.push_back(v);
iov[v]=n_v;
n_v++;
return true;
}
virtual bool insertE(string src,string dst,int weight=1){
insertV(src);
insertV(dst);
return insertE(iov[src],iov[dst],weight);
}
virtual bool insertE(int src,int dst,int weight=1)=0;
virtual bool removeE(string src,string dst){
if(iov.find(src)==iov.end() ||iov.find(dst)==iov.end() ) return false;
return removeE(iov[src],iov[dst]);
}
virtual bool removeE(int src,int dst)=0;
virtual void dfs(string v){
if(iov.find(v)==iov.end() ) return ;
visited.resize(n_v);
for(int i=0;i<n_v;i++)
visited[i]=false;
dfs(iov[v]);
}
};
//邻接矩阵
class MGraph:public Graph{
protected:
vector<vector<int>> M;
void setM(){
M.resize(n_v);
for(int i=0;i<n_v;i++){
M[i].resize(n_v);
for(int j=0;j<n_v;j++){
M[i][j]=INT_MAX;//
}
}
}
void dfs(int v){
cout<<vertices[v]<<" ";
visited[v]=true;
for(int i=0;i<n_v;i++){
if(!visited[i] && M[v][i]!=INT_MAX) dfs(i);
}
}
public:
MGraph(bool dir=false):Graph(dir){ }
MGraph(vector<string> v,bool dir=false):Graph(v,dir){setM();}
MGraph(int n,bool dir=false):Graph(n,dir){setM();}
void print(){
cout<<'\t';
// for(auto x:vertices) cout<<x<<'\t';
for(int i=0;i<n_v;i++)
cout<<vertices[i]<<'\t';
cout<<endl;
for(int i=0;i<n_v;i++){
cout<<vertices[i]<<":\t";
for(int j=0;j<n_v;j++)
{
if(M[i][j]==INT_MAX) cout<<"-\t";
else cout<<M[i][j]<<'\t';
}
cout<<endl;
}
cout<<endl;
}
void insertV(){
insertV(to_string(n_v));
}
bool insertV(string v){
bool r = Graph::insertV(v);
if(!r) return false;
//成功的话增加一行一列
for(int i=0;i<n_v-1;i++)
M[i].push_back(INT_MAX);
M.push_back(vector<int>(n_v,INT_MAX));
return true;
}
bool insertE(string src,string dst,int weight=1){
return Graph::insertE(src,dst,weight);
}
bool insertE(int src,int dst,int weight=1){
if(src<0||dst<0||src>=n_v||dst>=n_v) return false;
if(M[src][dst]!=INT_MAX) return false;
M[src][dst]=weight;
if(!directed) M[dst][src]=weight;
return true;
}
bool removeE(string src,string dst){
return Graph::removeE(src,dst);
}
bool removeE(int src,int dst){
if(src<0||dst<0||src>=n_v||dst>=n_v) return false;
if(M[src][dst]==INT_MAX) return false;
M[src][dst]=INT_MAX;
if(!directed) M[dst][src]=INT_MAX;
return true;
}
void dfs(string v){
Graph::dfs(v);
}
void bfs(string v){
if(iov.find(v)==iov.end() ) return ;
int iv=iov[v];
visited.resize(n_v);
for(int i=0;i<n_v;i++)
visited[i]=false;
queue<int> q;
cout<<v<<" ";
visited[iv]=true;
q.push(iv);
int w;
while(!q.empty()){
w=q.front();
q.pop();
for(int i=0;i<n_v;i++){
if(!visited[i]&&M[w][i]!=INT_MAX){
cout<<vertices[i]<<" ";
visited[i]=true;
q.push(i);
}
}
}
}
};
class LGraph:public Graph{
protected:
vector<map<int,int>> L;
void setL(){
L.resize(n_v);
for(auto x:L) x.clear();
}
void dfs(int v){
cout<<vertices[v]<<" ";
visited[v]=true;
for(auto x:L[v])
if(!visited[x.first])
dfs(x.first);
}
public:
LGraph(bool dir=false):Graph(dir){ }
LGraph(vector<string> v,bool dir=false):Graph(v,dir){setL();}
LGraph(int n,bool dir=false):Graph(n,dir){setL();}
void print(){
for(int i=0;i<n_v;i++){
cout<<vertices[i]<<"["<<i<<"]-->";
for(auto x:L[i])
cout<<x.first<<"("<<x.second<<") ";
cout<<endl;
}
}
void insertV(){
insertV(to_string(n_v));
}
bool insertV(string v){
bool r = Graph::insertV(v);
if(!r) return false;
//成功的话增加一行一列
L.push_back(map<int,int>());
return true;
}
bool insertE(string src,string dst,int weight=1){
return Graph::insertE(src,dst,weight);
}
bool insertE(int src,int dst,int weight=1){
if(src<0||dst<0||src>=n_v||dst>=n_v) return false;
if(L[src].find(dst)!=L[src].end()) return false;
L[src].insert(pair<int,int>(dst,weight));
if(!directed) L[dst].insert(pair<int,int>(src,weight)) ;
return true;
}
bool removeE(string src,string dst){
return Graph::removeE(src,dst);
}
bool removeE(int src,int dst){
if(src<0||dst<0||src>=n_v||dst>=n_v) return false;
if(L[src].find(dst)==L[src].end() ) return false;
L[src].erase(dst);
if(!directed) L[dst].erase(src) ;
return true;
}
void dfs(string v){
Graph::dfs(v);
}
void bfs(string v){
if(iov.find(v)==iov.end() ) return ;
int iv=iov[v];
visited.resize(n_v);
for(int i=0;i<n_v;i++)
visited[i]=false;
queue<int> q;
cout<<v<<" ";
visited[iv]=true;
q.push(iv);
int w;
while(!q.empty()){
w=q.front();
q.pop();
for(auto x:L[w]){
if(!visited[x.first]){
cout<<vertices[x.first]<<" ";
visited[x.first]=true;
q.push(x.first);
}
}
}
}
};
int main(){
vector<string> v={"AA","BB","CC","DD","EE"};
// MGraph g(v);
LGraph g(v);
g.insertE("AA","CC");
g.insertE(1,3);
g.insertE("DD","EE",6);
g.insertE("X","EE");
g.insertE("P","Q");
g.insertE("CC","X");
g.insertE("EE","BB");
// g.removeE("P","Q");
g.print();
// g.dfs("AA");
g.bfs("AA");
return 0;
}