NOIP前夕模板整理第一弹:图论

最短路模板: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

大概就这些了吧,图论(zhongyu)结束了,下面要开数据结构的坑了,我想静静
最后放张图,壮哉,我大基谷!
NOIP前夕模板整理第一弹:图论_第1张图片

你可能感兴趣的:(模板)