图论Word下载.docx
《图论Word下载.docx》由会员分享,可在线阅读,更多相关《图论Word下载.docx(52页珍藏版)》请在冰豆网上搜索。
![图论Word下载.docx](https://file1.bdocx.com/fileroot1/2022-11/27/707f1e89-c775-429c-a6b2-64c1edfb751c/707f1e89-c775-429c-a6b2-64c1edfb751c1.gif)
3、
问题再次被转化为“至少在缩点树上增加多少条树边,使得这棵树变为一个双连通图”。
若要使得任意一棵树,在增加若干条边后,变成一个双连通图,那么至少增加的边数=(这棵树总度数为1的结点数+1)/2
4、若low[v]>
dfn[u],则(u,v)为割边。
但是实际处理时我们并不这样判断,因为有的图上可能有重边,这样不好处理。
我们记录每条边的标号(一条无向边拆成的两条有向边标号相同),记录每个点的父亲到它的边的标号,如果边(u,v)是v的父亲边,就不能用dfn[u]更新low[v]。
这样如果遍历完v的所有子节点后,发现low[v]=dfn[v],说明u的父亲边(u,v)为割边。
voidtarjan(intx)
vis[x]=1;
dfn[x]=low[x]=++num;
for(inti=head[x];
i;
i=next[i])
if(!
vis[ver[i]])
p[ver[i]]=edge[i];
//记录父亲边
tarjan(ver[i]);
low[x]=min(low[x],low[ver[i]]);
elseif(p[x]!
=edge[i])//不是父亲边才更新
low[x]=min(low[x],dfn[ver[i]]);
if(p[x]&
&
low[x]==dfn[x])f[p[x]]=1;
//是割边
PS:
最大流=最小割
一、
1、邻接矩阵(略)
2、邻接链表
#include<
cstdio>
cstring>
algorithm>
usingnamespacestd;
constintN=102;
structEdgeNode
intto;
//终点
intw;
//权值
EdgeNode*next;
//指向下一条边的指针
EdgeNode()
{
next=NULL;
}
};
structVNode//起点表节点
intfrom;
//起点
EdgeNode*first;
//邻接表头指针
}Adjlist[N];
//整个图的邻接表
voidaddEdge(inta,intb,intwi)
EdgeNode*p=newEdgeNode();
p->
to=b;
w=wi;
next=Adjlist[a].first;
Adjlist[a].first=p;
voidprintEdge(intn)
for(inti=1;
i<
=n;
++i)
for(EdgeNode*k=Adjlist[i].first;
k!
=NULL;
k=k->
next)
printf("
vi=%d,vj=%d,w=%d\n"
i,k->
to,k->
w);
voiddelEdge(intn)//把申请的边的内存空间释放掉,防止超内存
EdgeNode*p=Adjlist[i].first;
EdgeNode*k=NULL;
while(p!
=NULL)
k=p->
next;
deletep;
p=k;
intvis[N];
voiddfs(intu)
vis[u]=1;
for(EdgeNode*k=Adjlist[u].first;
if(!
vis[k->
to])
dfs(k->
to);
voidinit(intn)
Adjlist[i].first=NULL;
memset(vis,0,sizeof(vis));
intmain()
intn,m;
while(scanf("
%d%d"
&
n,&
m)!
=EOF)
init(n);
for(inta,b,i=0;
m;
scanf("
a,&
b);
addEdge(a,b,1);
dfs
(1);
intres=0;
if(vis[i])
res++;
%d\n"
res);
delEdge(n);
return0;
3、链式前向星
constintM=102;
inthead[N];
inttot;
//已申请节点的个数
structEdge
intnext;
}edge[M];
voidaddEdge(intvi,intvj,intwi)
edge[tot].from=vi;
edge[tot].to=vj;
edge[tot].w=wi;
edge[tot].next=head[vi];
head[vi]=tot++;
for(inti=head[u];
i!
=-1;
i=edge[i].next)
vis[edge[i].to])
dfs(edge[i].to);
voidprintEdges(intn)
for(intj=head[i];
j!
j=edge[j].next)
i,edge[j].to,edge[j].w);
voidinit()
tot=0;
memset(head,-1,sizeof(head));
while(scanf("
init();
二、
1、Dijkstra
#include<
iostream>
queue>
#defineMAX0x3f3f3f3f
typedefpair<
int,int>
P;
structnode
intto,cost;
}edge[10000];
intcnt;
intn,start,end;
inthead[5000];
voidadd(intfrom,intto,intcost)
edge[cnt].to=to;
edge[cnt].cost=cost;
edge[cnt].next=head[from];
head[from]=cnt++;
voiddijkstra()
intdis[5000];
inti,v;
priority_queue<
P,vector<
P>
greater<
>
que;
nodee;
Pp;
fill(dis,dis+n,MAX);
dis[start]=0;
que.push(P(0,start));
while(!
que.empty())
p=que.top();
que.pop();
v=p.second;
if(dis[v]<
p.first)
continue;
for(i=head[v];
i!
i=edge[i].next)
e=edge[i];
if(dis[e.to]>
dis[v]+e.cost)
dis[e.to]=dis[v]+e.cost;
que.push(P(dis[e.to],e.to));
dis[end]==MAX?
-1:
dis[end]);
intm,from,to,cost;
while(~scanf("
m))
cnt=0;
while(m--)
%d%d%d"
from,&
to,&
cost);
add(from,to,cost);
add(to,from,cost);
start,&
end);
dijkstra();
2、spfa优化版(一般用于稀疏图)
deque>
constintN=501;
constintNN=100001;
constintinf=0x7fffffff;
intn,nu;
intvis[N],dis[N],num[N];
typedefstructnode
intadj,val;
structnode*next;
nodenode[NN],*p[N];
intSPFA(intstart)
deque<
int>
qu;
intx,i,a,b;
structnode*head[N];
for(i=1;
i++)
vis[i]=0;
num[i]=0;
dis[i]=inf;
head[i]=p[i];
vis[start]=1;
num[start]++;
qu.push_back(start);
qu.empty())
x=qu.front();
qu.pop_front();
vis[x]=0;
head[x]=p[x];
while(head[x])
a=head[x]->
adj;
b=head[x]->
val;
if(dis[a]>
dis[x]+b)
dis[a]=dis[x]+b;
if(!
vis[a])
vis[a]=1;
num[a]++;
if(num[a]>
=n)
return1;
//如果要求一条负环回路上的点只需在这里改改就行
dis[qu.front()])
qu.push_back(a);
else
qu.push_front(a);
head[x]=head[x]->
intt,i,m,w,a,b,c;
%d"
t);
while(t--)
memset(node,0,sizeof(node));
memset(p,0,sizeof(p));
nu=0;
m);
for(i=0;
b,&
c);
node[nu].adj=b;
node[nu].val=c;
node[nu].next=p[a];
p[a]=&
node[nu];
nu++;
node[nu].adj=a;
node[nu].next=p[b];
p[b]=&
if(SPFA
(1))
puts("
YES"
);
dis[n]);
3、第k短路
string>
map>
#defineinf0x7fffffff
constintmaxn=1010;
intd[maxn],head[maxn],head2[maxn],n,m,cnt;
boolvis[maxn];
intto,cost,next;
}edge[100010],edge2[100010];
structnode1
intv,g,f;
//f=g+h
booloperator<
(constnode1&
r)const
if(r.f==f)returnr.g<
g;
returnr.f<
f;
memset(head,-1,sizeofhead);
memset(head2,-1,sizeofhead2);
memset(d,0x3f,sizeofd);
voidaddedge(intfrom,intto,intcost)
head[from]=cnt;
edge2[cnt].to=from;
//反向存图找从终点到其他点的最短路径
edge2[cnt].cost=cost;
edge2[cnt].next=head2[to];
head2[to]=cnt++;
boolspfa(ints)
memset(vis,0,sizeofvis);
queue<
q;
d[s]=0;
q.push(s);
q.empty())
intnow=q.front();
q.pop();
vis[now]=0;
for(inti=head2[now];
i=edge2[i].next)
if(d[now]+edge2[i].cost<
d[edge2[i].to])
d[edge2[i].to]=d[now]+edge2[i].cost;
vis[edge2[i].to])
vis[edge2[i].to]=1;
q.push(edge2[i].to);
intastar(ints,intt,intk)
if(s==t)k++;
//起点=终点则最短路为0要注意哦
if(d[s]==inf)return-1;
node1>
intcnt2=0;
node1tmp,to;
tmp.v=s;
tmp.g=0;
tmp.f=tmp.g+d[tmp.v];
q.push(tmp);
tmp=q.top();
if(tmp.v==t)
cnt2++;
if(cnt2==k)
returntmp.g;
for(inti=head[tmp.v];
to.v=edge[i].to;
to.g=tmp.g+edge[i].cost;
to.f=to.g+d[to.v];
q.push(to);
return-1;
intfrom,to,cost,start,end,k;
for(inti=0;
addedge(from,to,cost);
end,&
k);
spfa(end);
intans=astar(start,end,k);
ans);
4、Floyd
stdio.h>
#defineMAX1000000000
intn,m,p,i,j,st,end,q,d,k,t,time;
intdis[210],map[210][210];
intMin(inta,intb)
returna<
b?
a:
b;
voidfloyd()
for(k=1;
k<
k++)
for(j=1;
j<
j++)
map[i][j]=Min(map[i][j],map[i][k]+map[k][j]);
%d%d%d%d"
m,&
p,&
t)!
for(j=0;
j++)
map[i][j]=MAX;
map[i][i]=0;
}//将每一个区域之间的连接时间初始化为最大值,同一地区因为不需要花费时间移动所以初始化为0
st,&
map[st][end]=map[end][st]=1;
}//将数据中彼此连接的区域的连接时间赋值为1
floyd();
q);
while(q--)
d,&
time);
ints=map[p][d];
if(s>
time||s>
t)
YES\n"
NO\n"
}//判断能否起飞。
。
没什么好说的
\n"
三、
1、isap最大流
memory.h>
cmath>
#defineMAXN10005
#defineMAXE200000
#defineINF1e9
inttmp,src,des,cnt;
intn,m;
intfrom,to;
intnext,cap;
}edge[MAXE];
inthead[MAXN];
intgap[MAXN],dep[MAXN],cur[MAXN],stack[MAXN],top;
intISAP()
intcurfLow,maxfLow,u,insert,i;
memset(dep,0,sizeof(dep));
memset(gap,0,sizeof(gap));
memcpy(cur,head,n);
maxfLow=0;
u=src;
top=0;
while(dep[src]<
n)//整个循环当源点s的距离标号dep[s]>
=n时结束.
if(u==des)//当前顶点i为终点时增广
curfLow=INF;
top;
if(curfLow>
edge[stack[i]].cap)
insert=i;
curfLow=edge[stack[i]].cap;
++i