1、邻接表的存储

#include<stdio.h>
#include<stdlib.h>
#include<string.h> 
#define MAXN 10000
struct {
	int value; //用来存边的权值
	int to;   //用来存边的末端
	int next;// 用来储存下一条边的编号
}edges[MAXN];
int cnt = 0; //第一边的编号为零
int head[MAXN]; //储存以 i 为 始点的边的编号
void init(){
	memset(head,-1,sizeof(head)); //初始化每个点均没在边中
}
void add(int u,int v,int value){
	edges[cnt].to = v; //编号为 cnt的边的末端
	edges[cnt].value = value; //边的权值
	edges[cnt].next = head[u]; //下一条以u为始点的编号
	head[u] = cnt ++;//以当前点为始点的编号为 cnt
	edges[cnt].to = u; //因为我存的是无向图 所以 要再以v为始点存一遍
	edges[cnt].value = value;
	edges[cnt].next = head[v];
	head[v] = cnt ++;
}
 
void Print(int n){
	int i,j;
	for (i=1;i<=n;i++)
	{
		for (j=head[i];j!=-1;j=edges[j].next) 一开始j为 以i为始点的边的编号 当j!=-1 时说明以i为始点的边还有,他在 edges[j].next 中存着
		{
			printf("%d->%d = %d\n",i,edges[j].to,edges[j].value);
		}
	}
}
int main (){
	int n,m,i,u,v,value;
	scanf("%d%d",&n,&m);
	init();
	for (i=0;i<m;i++)
	{
		scanf("%d%d%d",&u,&v,&value);
		add(u,v,value);
	}
	Print(n);
} 

2、拓扑排序

    queue<int>q;
    vector<int>edge[n];
    for(int i=0;i<n;i++)  //n  节点的总数
        if(in[i]==0) q.push(i);  //将入度为0的点入队列
    vector<int>ans;   //ans 为拓扑序列
    while(!q.empty())
    {
        int p=q.front(); q.pop(); // 选一个入度为0的点,出队列
        ans.push_back(p);
        for(int i=0;i<edge[p].size();i++)
        {
            int y=edge[p][i];
            in[y]--;
            if(in[y]==0)
                q.push(y);  
        }
    }
    if(ans.size()==n)   
    {
        for(int i=0;i<ans.size();i++)
            printf( "%d ",ans[i] );
        printf("\n");
    }
    else printf("No Answer!\n");   //  ans 中的长度与n不相等,就说明无拓扑序列

3、dijsktra的堆优化

 1 #include <cstdio>
 2 #include <queue>
 3 #include <iostream>
 4 #include <algorithm>
 5 using namespace std;
 6 int n,m,s;
 7 int head[100001],dis[100001],cnt;
 8 bool vis[100001];
 9 struct qwq{
10     int from,to,next;
11     long long len;
12 }edge[200001];
13 void add(int u,int v,int w)
14 {
15     cnt++;
16     edge[cnt].from=u;
17     edge[cnt].to=v;
18     edge[cnt].len=w;
19     edge[cnt].next=head[u];
20     head[u]=cnt;
21     return;
22 }
23 struct node{
24     int index,dist;
25     bool operator < (const node &x)const
26     {
27         return dist>x.dist;
28     }
29 };
30 priority_queue<node> q; 
31 int main()
32 {
33     scanf("%d%d%d",&n,&m,&s);
34     for(int i=1;i<=m;i++)
35     {
36         int u,v,w;
37         scanf("%d%d%d",&u,&v,&w);
38         add(u,v,w);
39     }
40     for(int i=1;i<=n;i++)
41     dis[i]=2147483647;
42     dis[s]=0;
43     q.push(node{s,0});
44     while(!q.empty())
45     {
46         node x=q.top();
47         q.pop();
48         int u=x.index;
49         if(vis[u]) continue;
50         vis[u]=1;
51         for(int i=head[u];i;i=edge[i].next)
52         {
53             if(dis[edge[i].to]>dis[u]+edge[i].len)
54             {
55                 dis[edge[i].to]=dis[u]+edge[i].len;
56                 q.push(node{edge[i].to,dis[edge[i].to]});
57             }
58         }
59     }
60     for(int i=1;i<=n;i++)
61     printf("%d ",dis[i]);
62     return 0;
63 }

4、欧拉回路

dfs例题
fleury解释
fleury算法:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <climits>
#include <vector>
#include <queue>
#include <cstdlib>
#include <string>
#include <set>
#include <stack>
#define LL long long
#define pii pair<int,int>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 1000;
bool e[maxn][maxn];
int n,m;
stack<int>stk;
void dfs(int u){
    stk.push(u);
    for(int i = 1; i <= n; i++){
        if(e[u][i]){
            e[u][i] = false;
            e[i][u] = false;
            dfs(i);
            break;
        }
    }
}
void Fleury(int x){
    while(!stk.empty()) stk.pop();
    stk.push(x);
    int i;
    while(!stk.empty()){
        int u = stk.top();
        stk.pop();
        for(i = 1; i <= n; i++)
            if(e[u][i]) break;
       if(i <= n) dfs(u); else printf("%d ",u);
    }
    puts("");
}
int main() {
    int u,v,cnt,degree,st;
    while(~scanf("%d %d",&n,&m)){
        memset(e,false,sizeof(e));
        for(int i = 0; i < m; i++){
            scanf("%d %d",&u,&v);
            e[u][v] = e[v][u] = true;
        }
        cnt = 0;
        st = 1;
        for(int i = 1; i <= n; i++){
            for(int j = 1,degree = 0; j <= n; j++)
                if(e[i][j]) degree++;
            if(degree&1){
                st = i;
                cnt++;
            }
        }
        if(cnt == 2 || !cnt) Fleury(st);
        else puts("No Euler path");
    }
    return 0;
}

5、tarjan求强联通分量

强连通分量+割点+桥

#include<iostream>
#include<algorithm>
#include<cstring>
#include<stack> 
using namespace std;
 
struct ss{
	int v;
	int next;
	/*  
	v指节点v 
	next永远指u点->上一个点的边序(1,2,3···)
	边序 即u到其他点(上一个点)是第几条边(num) 
	上一条边没有就是-1 
	*/ 
}s[1000]; 
 
int head[1000];//边序 
int dfn[1000];
int low[1000];
int vis[1000];//相当于栈 
int color[1000];//染色 
int n,m;
int cnt;
int num;
stack<int >st;
 
void init()
{
	memset(head,-1,sizeof(head));
	memset(vis,0,sizeof(vis));
	memset(dfn,0,sizeof(dfn));
	memset(low,0,sizeof(low));
	//memset(color,0,sizeof(color));	
	num=0;
	cnt=0;
}
void add(int u,int v)
{
	s[num].v = v;
	s[num].next = head[u];
	head[u] = num++;
	/*
	将v存进去
	将u->上一个点的边序挂上next
	num一直在++(总边数不会错)
	head[u]更新当前u的边序 			
	如果双向再存u挂v边序 
	eg[num].v = u;
	eg[num].next = head[v];
	head[v] = num++;
	*/ 	
}
void Tarjan(int u)
{
	st.push(u);
	dfn[u] = low[u] = ++cnt;//搜索次序号 
	vis[u]=1;//节点x在栈中
	for(int i = head[u]; i != -1; i = s[i].next)
	{
		//通过对u点上一个边序的挂钩
		//构造对连接u点的所有边数遍历查找对应v点 
		int v = s[i].v;
		if(!dfn[v])//不曾访问过 
		{
			Tarjan(v);//找v点 
			low[u] = min(low[u],low[v]);
			/* 
			根节点的dfn值是区分不同环的值
                        low是为了让这个环都等dfn[根]
                        low[根]可能不等dfn[根]
                        根的low继承根的根的dfn 
			1.如果v是根节点
			  不论只有v一个点还是有一个环 
			  low[v]确实永远比low[u]大(u比v先入)
			  v的环low值=dfn[v]都比low[u]的大 
			  v不对u产生影响
			2. 
			  如果v点与u点成环
			  那么顺着v点或v连着的点找下去
			  总有一个能连到根节点
			  low值回溯的时候继承根的dfn值
                          根的dfn是这个环里面最小的
			  low[v]等于dfn[根]
			  v对u产生影响->low[u]=low[v] 
			*/ 
		}
		else if(vis[v])//访问过但还在栈中 
			/*
			因为根u点还没有将边都找完
			出栈的点都是根节点边已经找完的点或者环 
			已经没有与剩下的点有任何关系才能出 
			*/ 
			low[u] = min(low[u],dfn[v]);
			/*
			这相当于根节点有两个分叉口a,b 
			并且a找到已经在栈中的b
				  
			那么这一步其实也可以写成 
			low[u] = min(low[u],low[v]);
                        反正连到一个环了
		
                        目的是为了让缩点与割点的代码一致 
                        区分相连的环的根有不同的dfn
                        无向图找割点用的
                        但是缩点是将一起出栈的点缩成一个点(染成一个色)
	                对于缩点结果都无影响	
			*/
	}	
 
	if(dfn[u]==low[u])//找一遍再是强连通分量 
	{
		int now;
		do{	//取出包括u的环 
			now=st.top();
			color[now]=u; //染色 
			vis[now]=0;
			st.pop();
		}while(now!=u);
	}
	return;	
} 
void out()
{
	for(int i=1;i<=n;i++)
		printf("%d ",i);
	printf("\n");
	for(int i=1;i<=n;i++)
		printf("%d ",color[i]);
	printf("\n");
}
 
int main()
{
	while(~scanf("%d%d",&n,&m) && (m+n))
	{
		init();
		int u,v;
		while(m--)
		{
			scanf("%d%d",&u,&v);	
			add(u,v);
		}	
		//为了防止一个图里有不相连的两个或多个树 
		for(int i=1;i<=n;i++) 
			if(!dfn[i]) 
				Tarjan(i);
		out();
	} 
	return 0; 
} 

匈牙利算法和km算法

白话描述匈牙利算法
KM算法+模板

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C语言是一种广泛使用的编程语言,它具有高效、灵活、可移植性强等特点,被广泛应用于操作系统、嵌入式系统、数据库、编译器等领域的开发。C语言的基本语法包括变量、数据类型、运算符、控制结构(如if语句、循环语句等)、函数、指针等。下面详细介绍C语言的基本概念和语法。 1. 变量和数据类型 在C语言中,变量用于存储数据,数据类型用于定义变量的类型和范围。C语言支持多种数据类型,包括基本数据类型(如int、float、char等)和复合数据类型(如结构体、联合等)。 2. 运算符 C语言中常用的运算符包括算术运算符(如+、、、/等)、关系运算符(如==、!=、、=、<、<=等)、逻辑运算符(如&&、||、!等)。此外,还有位运算符(如&、|、^等)和指针运算符(如、等)。 3. 控制结构 C语言中常用的控制结构包括if语句、循环语句(如for、while等)和switch语句。通过这些控制结构,可以实现程序的分支、循环和多路选择等功能。 4. 函数 函数是C语言中用于封装代码的单元,可以实现代码的复用和模块化。C语言中定义函数使用关键字“void”或返回值类型(如int、float等),并通过“{”和“}”括起来的代码块来实现函数的功能。 5. 指针 指针是C语言中用于存储变量地址的变量。通过指针,可以实现对内存的间接访问和修改。C语言中定义指针使用星号()符号,指向数组、字符串和结构体等数据结构时,还需要注意数组名和字符串常量的特殊性质。 6. 数组和字符串 数组是C语言中用于存储同类型数据的结构,可以通过索引访问和修改数组中的元素。字符串是C语言中用于存储文本数据的特殊类型,通常以字符串常量的形式出现,用双引号("...")括起来,末尾自动添加'\0'字符。 7. 结构体和联合 结构体和联合是C语言中用于存储不同类型数据的复合数据类型。结构体由多个成员组成,每个成员可以是不同的数据类型;联合由多个变量组成,它们共用同一块内存空间。通过结构体和联合,可以实现数据的封装和抽象。 8. 文件操作 C语言中通过文件操作函数(如fopen、fclose、fread、fwrite等)实现对文件的读写操作。文件操作函数通常返回文件指针,用于表示打开的文件。通过文件指针,可以进行文件的定位、读写等操作。 总之,C语言是一种功能强大、灵活高效的编程语言,广泛应用于各种领域。掌握C语言的基本语法和数据结构,可以为编程学习和实践打下坚实的基础。
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值