1.邻接矩阵
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;
int n,m,z[110][110];
int main()
{
scanf("%d%d",&n,&m);
for (int a=1;a<=m;a++)
{
int s,e;
scanf("%d%d",&s,&e);
z[s][e]=1;
z[e][s]=1;
}
for (int a=1;a<=m;a++)
{
int s,e,d;
scanf("%d%d%d",&s,&e,&d);
z[s][e]=d;
}
return 0;
}
2.邻接表
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;
const int maxn=100010;
const int maxm=200010;
int n,en,first[maxn];//first[i]代表当前第i个点的链表的第一条边的编号
struct edge
{
int e,d;//e代表这条边的终点 d代表这条边的长度
int next;//链表里面下一条边的编号
}ed[maxm];
void add_edge(int s,int e,int d)
{
en++;
ed[en].e=e;ed[en].d=d;
ed[en].next = first[s];
first[s] = en;
}
int main()
{
scanf("%d%d",&n,&m);
for (int a=1;a<=m;a++)
{
int s,e,d;
scanf("%d%d%d",&s,&e,&d);
add_edge(s,e,d);
}
int now;
for (int p=first[now];p!=0;p=ed[p].next)
printf("%d---->%d",now,ed[p].e);
return 0;
}
3.判断二分图
判断二分图方法-染色法:用两种颜色,对所有顶点逐个染色,且相邻顶点染不同的颜色,如果发现相邻顶点染了同一种颜色,则此图不是二分图。 当所有顶点都被染色,且没有发现同色的相邻顶点,就说明是二分图,退出。
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;
const int maxn=100010;
const int maxm=200010;
int n,en,first[maxn];//first[i]代表当前第i个点的链表的第一条边的编号
int col[maxn];//col[i]=0 代表i点还没有被分到左边或者右边
//coi[i]=1 代表i分到了左边
//col[i]=2 代表i分到了右边
struct edge
{
int e;//e代表这条边的终点
int next;//链表里面下一条边的编号
}ed[maxm];
void add_edge(int s,int e)
{
en++;
ed[en].e=e;
ed[en].next = first[s];
first[s] = en;
}
int main()
{
scanf("%d%d",&n,&m);
for (int a=1;a<=m;a++)
{
int s,e;
scanf("%d%d",&s,&e);
add_edge(s,e);
add_edge(e,s);
}
col[1]=1;
queue<int> q;//队列面存的点是那些周围点需要被标记的点
q.push(1);
while (q.size()!=0)
{
int now=q.front();
q.pop();
for (int p=first[now];p!=0;p=ed[p].next)
{
int e=ed[p].e;//now --- e
if (col[e]==0)
{
col[e]=3-col[now];
q.push(e);
}
else
{
if (col[e]==col[now])
{
printf("No\n");
return 0;
}
}
}
}
printf("Yes\n");
return 0;
}
4.LCA 最近公共祖先
O(nm)版
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;
const int maxn=100010;
const int maxm=200010;
int n,en,first[maxn];//first[i]代表当前第i个点的链表的第一条边的编号
int f[maxn],depth[maxn];//f[i]代表i号点的父亲 depth[i]代表i号点的深度
struct edge
{
int e;//e代表这条边的终点
int next;//链表里面下一条边的编号
}ed[maxm];
void add_edge(int s,int e)
{
en++;
ed[en].e=e;
ed[en].next = first[s];
first[s] = en;
}
void dfs(int now)//处理出now所有儿子节点的深度与父亲
{
for (int p=first[now];p!=0;p=ed[p].next)
{
int e=ed[p].e;//now -- e
if (e!=f[now])
{
depth[e]=depth[now]+1;
f[e]=now;
dfs(e);
}
}
}
int get_lca(int p1,int p2)//O(n)
{
if (depth[p1]<depth[p2]) swap(p1,p2);
while (depth[p1]>depth[p2])
p1=f[p1];
while (p1!=p2)
p1=f[p1],p2=f[p2];
return p1;
}
int main()
{
scanf("%d%d",&n,&m);
for (int a=1;a<n;a++)
{
int s,e;
scanf("%d%d",&s,&e);
add_edge(s,e);
add_edge(e,s);
}
depth[1]=1;
dfs(1);
for (int a=1;a<=m;a++)//O(nm)
{
int p1,p2;
scanf("%d%d",&p1,&p2);
printf("%d\n",get_lca(p1,p2));
}
return 0;
}