最短路模板:SPFA 、 dijkstra 、floyd
SPFA和dijsktra之前整理过了,直接放链接吧
点这里O(∩_∩)O
floyd用处很广,可以用来求多源最短路,例题codevs1077 多源最短路这里放一下核心代码
for(int k = 1 ; k <= n ;k++)
for(int i = 1 ; i <= n ; i++)
for(int j =1 ; j <= n ; j++)
{
if(di[i][j]>di[i][k]+di[k][j])
di[i][j]=di[i][k]+di[k][j];
}
次短路:例题:匈牙利游戏
#include
#include
#include
#include
#include
#define MAXN 200000+5
using namespace std;
int head[MAXN],dis[MAXN],dis2[MAXN],nxt[MAXN<<1],tot,n,m;
bool vis[MAXN],flag = 0;
struct Edge
{
int from,to,cost;
}es[MAXN << 1];
void build(int f,int t,int d)
{
es[++tot]=(Edge){f,t,d};
nxt[tot] = head[f];
head[f] = tot;
}
queue<int>q;
void spfa(int s)
{
memset(dis,0x3f,sizeof(dis));
memset(dis2,0x3f,sizeof(dis2));
dis[s] = 0;
vis[s] = 1;
q.push(s);
while(!q.empty())
{
int x = q.front();
q.pop();
vis[x] = 0;
for(int i = head[x] ; i ; i = nxt[i])
{
Edge e = es[i];
if(dis[e.to] > dis[x]+e.cost)//如果这条路能更新最短路,就把之前
{ //的最短路更新成次短路
dis2[e.to ] = dis[e.to ];
dis[e.to] = dis[x]+e.cost;
if(!vis[e.to])
{
q.push(e.to );
vis[e.to] = 1;
}
}
else if(dis[e.to] < dis[x]+e.cost && dis2[e.to ] > dis[x]+e.cost)
{//如果这条路比最短路要长,比次短路要短,就更新次短路
dis2[e.to ] = dis[x] + e.cost;
if(!vis[e.to ])
{
q.push(e.to);
vis[e.to] = 1;
}
}
if(dis2[e.to ] > dis2[x]+e.cost)
{//用新的次短路更新次短路,跟最短路的方法一样
dis2[e.to] = dis2[x]+e.cost;
if(!vis[e.to])
{
q.push(e.to);
vis[e.to] = 1;
}
}
}
}
if(dis2[n] >= 1061109567)
flag = 1;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i = 1; i <= m; i ++)
{
int aa,bb,cc;
scanf("%d%d%d",&aa,&bb,&cc);
build(aa,bb,cc);
}
spfa(1);
if(flag)
puts("-1");
else
cout <return 0;
}
最小生成树模板:
kruskal算法和prime算法,思想的话,这篇博文(点击(╯▽╰))比较简洁易懂,具体实现没讲,看看代码就行了吧
代码:
kruskal
#include
#include
#include
#include
#define MAXN 200000
using namespace std;
int tot=0,fa[MAXN],n;
struct Edge
{
int x,y,v;
}a[MAXN];
void build(int f,int t,int d)
{
a[++tot] = (Edge){f,t,d};
}
bool cmp(Edge a,Edge b)
{
return a.v < b.v;
}
int find(int x)
{
return fa[x] == x?x:fa[x] = find(fa[x]);
/*
if(fa[x] == x)
return x;
else
fa[x] = find(fa[x]);
return fa[x];
*/
}
int main()
{
scanf("%d",&n);
int cos;
for(int i = 1; i <= n; i ++)
for(int j = 1; j <= n; j ++)
{
scanf("%d",&cos);
build(i,j,cos);
}
sort(a+1,a+tot+1,cmp);
for(int i = 1; i <= n*n; i ++)
fa[i] = i;
int sum = 0;
for(int i = 1; i <= tot ; i ++)
{
int x = find(a[i].x);
int y = find(a[i].y);
if(x != y)
{
fa[x] = y;
sum += a[i].v;
}
}
printf("%d",sum);
return 0;
}
prime算法:
#include
#include
#include
#include
#define MAXN 50000
using namespace std;
int n,lowcost[MAXN],sum=0,map[500][500];
bool vis[MAXN];
void prime()
{
int tmp,k;
memset(vis,0,sizeof(vis));
for(int i = 1; i <= n; i ++)
lowcost[i] = map[1][i];
for(int j = 1; j <= n; j ++)
{
tmp = 2147483647;
for(int i = 1; i <= n; i ++)
{
if(!vis[i] && tmp > lowcost[i])
{
tmp = lowcost[i];
k = i;
}
}
if(tmp == 2147483647)
break ;
vis[k] = 1;
sum += tmp;
for(int i = 1; i <= n; i ++)
if(!vis[i] && lowcost[i] > map[k][i])
lowcost[i] = map[k][i];
}
}
int main()
{
scanf("%d",&n);
int cos;
for(int i = 1; i <= n; i ++)
for(int j = 1; j <= n; j ++)
{
scanf("%d",&cos);
map[i][j] = cos;
}
prime();
printf("%d\n",sum);
return 0;
}
差分约束:例题codevs1242布局
原帖题解:戳(=^_^=)
代码:
#include
#include
#include
#include
#include
using namespace std;
const int MAXN = 200000;
int head[MAXN],dist[MAXN],nxt[MAXN],tim[MAXN],st,se,ml,md,tot=0,n,m;
bool vis[MAXN],flag=0;
struct Edge
{
int from,to,cost;
}edge[MAXN <<2];
void build(int f,int t,int d)
{
edge[++tot].to = t;
edge[tot].from = f;
edge[tot].cost = d;
nxt[tot] = head[f];
head[f] = tot;
}
queue <int >q;
void spfa(int s)
{ memset(dist,0x7f,sizeof(dist));
memset(vis,0,sizeof(vis));
dist[s] = 0;
vis[s] = 1;
q.push(s);
while(!q.empty())
{
int x = q.front();
q.pop();
vis[x] = 0;
for(int i = head[x];i;i = nxt[i])
{
int e = edge[i].to;
if(++tim[e] > n)
{
flag = 1;
return ;
}
if(dist[e] > dist[x] + edge[i].cost)
{
dist[e] = dist[x] + edge[i].cost;
if(!vis[e])
{
vis[e] = 1;
q.push(e);
}
}
}
}
}
int main()
{
scanf("%d%d%d",&n,&ml,&md);
for(int i = 1; i <= ml; i ++)
{
int aa,bb,cc;
scanf("%d%d%d",&aa,&bb,&cc);
build(aa,bb,cc);
}
for(int i = 1; i <= md; i ++)
{
int aa,bb,cc;
scanf("%d%d%d",&aa,&bb,&cc);
build(bb,aa,-cc);
}
spfa(1);
if(flag)
puts("-1");
else if(dist[n]==2139062143)
puts("-2");
else
cout << dist[n] <return 0;
}
tarjan求scc模板:例题bzoj&&poj受欢迎的牛
写了份tarjan学习笔记,代码全程注释,点击就送233
#include
#include
#include
#include
#include
#define MAXN 100000
using namespace std;
int blt[MAXN],to[MAXN],tot,head[MAXN],nxt[MAXN],n,m,scc[MAXN],sz[MAXN],scccnt = 0;
struct Edge
{
int from,too;
}e[MAXN];
void build(int f,int t)
{
to[++tot] = t;
nxt[tot] = head[f];
head[f] = tot;
}
int dfn[MAXN],low[MAXN],tim=0;
stack <int>s;
void dfs(int u)
{
s.push(u);
dfn[u] = low[u] = ++tim;
int v;
for(int i = head[u]; i ; i = nxt[i])
{
v = to[i];
if(!dfn[v])
{
dfs(v);
low[u] = min(low[u],low[v]);
}
else if(!scc[v])
{
low[u] = min(low[u],dfn[v]);
}
}
if(low[u] == dfn[u])
{
int x;
scccnt ++;
while(!s.empty())
{
x = s.top();
s.pop();
scc[x] = scccnt;
sz[scccnt]++;
if(u == x)
break;
}
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i = 1; i <= m; i ++)
{
scanf("%d%d",&e[i].from,&e[i].too );
build(e[i].from ,e[i].too);
}
for(int i = 1; i <= n; i ++)
if(!dfn[i])
dfs(i);
for(int i = 1; i <= m; i ++)
{
if(scc[e[i].from ] != scc[e[i].too ])
{
blt[scc[e[i].from ]] ++;
}
}
int q = 0,ans=0;
for(int i = 1; i <= scccnt; i ++)
{
if(!blt[i])
{
ans = sz[i];
q ++;
}
}
if(q == 1)
printf("%d\n",ans);
else
puts("0");
return 0;
}
求最近公共祖先
例题poj1330
模板,,,放个链接吧,暴力版和倍增版的http://blog.csdn.net/cherish_k/article/details/52924358
分层图:
例题:bzoj2763飞行路线和bzoj冻结
篇幅太长啦,SPFA和dijkstra两个版本
放个链接http://blog.csdn.net/cherish_k/article/details/52936177