拓扑排序 B3644

# include<iostream>
# include<cstdio>
# include<vector>
# include<queue>
using namespace std;

const int M=105;
int n,t,d[M];
vector<int> e[M];
queue<int> q;

void toposort(){
	for(int i=1;i<=n;++i)
		if(d[i]==0) q.push(i);
	while(!q.empty()){
		int u=q.front();
		q.pop();
		cout<<u<<" ";
		for(int i=0,len=e[u].size();i<len;++i){
			int v=e[u][i];
			d[v]--;
			if(d[v]==0) q.push(v);
		}
	}
}

int main(){
	cin>>n;
	for(int i=1;i<=n;++i)
		while(true){
			cin>>t;
			if(t==0) break;
			e[i].push_back(t);
			d[t]++;
		}
	toposort();
	return 0;
}

单源最短路径模板 P3371 P4779

详见 最短路 合集

最小生成树 P3366

Kruskal

时间复杂度: O(mlogm) O(m \log m)

# include<iostream>
# include<algorithm>
using namespace std;

const int N=5e3+5,M=2e5+5;

struct edge{
	int u,v,w;
	void in(){
		cin>>u>>v>>w;
	}
}e[M];

int n,m,fa[N],k=0,s=0;

bool cmp(edge a,edge b){
	if(a.w!=b.w) return a.w<b.w;
	else return a.u!=b.u?a.u<b.u:a.v<b.v;
}

int find(int u){
	if(u==fa[u]) return u;
	return fa[u]=find(fa[u]);
}

void kruskal(){
	sort(e,e+m,cmp);
	for(int i=1;i<=n;++i) fa[i]=i;
	for(int i=0;i<m;++i){
		int u=e[i].u,v=e[i].v,w=e[i].w;
		int p=find(u),q=find(v);
		if(p!=q){
			s+=w;++k;
			fa[u]=fa[p]=q;
		}
		if(k==n-1) return;
	}
}

int main(){
	cin>>n>>m;
	for(int i=0;i<m;++i) e[i].in();
	kruskal();
	if(k==n-1) cout<<s;
	else cout<<"orz";
	return 0;
}

Prim堆优化

时间复杂度: O((n+m)logn) O((n+m) \log n)

# include<iostream>
# include<queue>
# include<vector>
# include<map>
using namespace std;
# define m(a,b) make_pair(a,b)
# define p pair<int,int>

struct edge{
	int v,w;
};

const int N=1e5+5,inf=0x7fffffff; 
int n,m,x,y,z,sum,k=0;
int dis[N],cnt[N];
bool vis[N];
vector<edge> e[N];
priority_queue<p,vector<p>,greater<p> > q;

void add(int x,int y,int z){
	e[x].push_back({y,z});
	++cnt[x];
}

void prim(){
	for(int i=1;i<=n;++i) dis[i]=inf;
	dis[1]=0;
	q.push(m(0,1));
	while(!q.empty()){
		int u=q.top().second,d=q.top().first;
		q.pop();
		if(vis[u]) continue;
		vis[u]=1;
		++k;
		sum+=d;
		if(k>=n) break;
		for(int i=0;i<cnt[u];++i){
			int v=e[u][i].v,w=e[u][i].w;
			if(w<dis[v]){
				dis[v]=w;
				q.push(m(w,v));
			}
		}
	}
}

int main(){
	cin>>n>>m;
	for(int i=0;i<m;++i){
		cin>>x>>y>>z;
		add(x,y,z);
		add(y,x,z);
	}
	prim();
	if(k==n) cout<<sum;
	else cout<<"orz";
	return 0;
}

强连通分量及其应用

详见 强连通分量 合集