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

来源:互联网 发布:安卓魔音软件 编辑:程序博客网 时间:2024/05/22 17:46

最短路模板: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 <cstdio>#include <iostream>#include <algorithm>#include <cstring>#include <queue>#define MAXN 200000+5using 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 <<dis2[n]<<endl;    return 0;}

最小生成树模板:
kruskal算法和prime算法,思想的话,这篇博文(点击(╯▽╰))比较简洁易懂,具体实现没讲,看看代码就行了吧
代码:
kruskal

#include <cstdio>#include <iostream>#include <algorithm>#include <cstring>#define MAXN 200000using 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 <iostream>#include <algorithm>#include <cstring>#include <cstdio>#define MAXN 50000using 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 <cstdio>#include <iostream>#include <cstring>#include <algorithm>#include <queue>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] <<endl;    return 0;}

tarjan求scc模板:例题bzoj&&poj受欢迎的牛
写了份tarjan学习笔记,代码全程注释,点击就送233

#include <cstdio>#include <iostream>#include <cstring>#include <algorithm>#include <stack>#define MAXN 100000using 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)结束了,下面要开数据结构的坑了,我想静静
最后放张图,壮哉,我大基谷!
壮哉,我大基谷

1 0