最小生成树
生成树:一个连通无向图的生成子树,同时要求是树。也即在图的边集中选择n - 1条,将所有顶点连通
我们定义无向连通图的最小生成树为边权和最小的生成树
注意:只有连通图才有生成树,而对于非连通图,只存在生成森林
Kruskal算法
#include<bits/stdc++.h>
using namespace std;
const int MAX = 1e6+1;
struct NODE{//存放边
int u;
int v;
int w;
}e[MAX];
int cnt;//记录边的数量
int fa[MAX];//并查集 记录祖先
int flag;//标志
int sum;//记录边权和
int n,m;//点,边
int num;//记录加入边的数量
void add(int x,int y,int w){//加边
e[++cnt].u = x;
e[cnt].v = y;
e[cnt].w = w;
}
void ini(){//初始化
flag = 0;
sum = 0;
cnt = 0;
num = 0;
for(int i = 1;i <= n;i++)
fa[i] = i;
}
int find(int x){
if(fa[x] != x)//说明该结点还能向上溯源
fa[x] = find(fa[x]);//路径压缩,把该结点的父节点更新为根节点(祖先)
return fa[x];//返回祖先
}
void kruskal(){
for(int i = 1;i <= cnt;i++){
int x = find(e[i].u);
int y = find(e[i].v);
if(x == y)//如果两个结点祖先相同,说明两点已经连通
continue;
fa[x] = y;//否则赋值使其连通
sum += e[i].w;//计算权值和
if(++num == n - 1){//加边条数等于n-1条时说明已经连通
flag = 1;
break;
}
}
}
bool cmp(struct NODE a,struct NODE b){//重载sort函数
return a.w < b.w;
}
int main(){
while(cin>>n>>m){//顶点数 边数
ini();
while(m--) {
int x, y, w;
cin>>x>>y>>w;
add(x, y, w);
}
sort(e,e+cnt,cmp);//按照边权排序
kruskal();
if(flag)
printf("%d\n",sum);
else{
cout<<"无法生成最小生成树"<<endl;
}
}
return 0;
}
KMP
#include<bits/stdc++.h>
using namespace std;
char str[100010];//测试串(模式串)
char s[100010];//主串(被测串)
int n[100010]={0};//next数组
void calnext(){
int len = strlen(str);
for(int j = 1,p = 0;j < len;j++){
while(p > 0 && str[p] != str[j])//长度为1或者目前字符不匹配时利用失败函数提前跳转
p = n[p-1];//从上个字符匹配完位置开始匹配
if(str[p] == str[j])
p++;
n[j] = p;
//cout<<j<<" "<<p<<endl;
}
for(int i = 0;str[i] != '\0';i++)
cout<<n[i]<<' ';
cout<<endl;
}
int kmp(){
calnext();
int len = strlen(str);//模式串的长度
for(int i = 0,j = 0;s[i] != '\0';i++){
while(j > 0 && s[i] != str[j])
j = n[j-1];
if(s[i] == str[j])
j++;
if(j == len)//匹配完成
return i - len + 1;
}
return -1;
}
int main(){
cin>>s;
cin>>str;
int flag = kmp();
if(flag != -1){
cout<<"匹配位置在:"<<flag;
}
else
cout<<"无法匹配";
return 0;
}
/*
abbbbabab
bbbba
*/