Bellman及其优化

来源:互联网 发布:弹丸论破未来篇 知乎 编辑:程序博客网 时间:2024/06/07 05:48
#include<iostream>#include<algorithm>#include<cstdio>#include<cstring>#include<queue>#include<vector>#include<set>#include<ctime>#define MAXX 1e6using namespace std;int first[1000010],NEXT[1000010],u[1000010],v[1000010],w[1000010],cont,dis[1000010],vis[1000010];//c存起点,v存终点,w存权值int N,M,S,T;bool buildmap(int a,int b,int c)//建图{    u[cont]=a,v[cont]=b,w[cont]=c;//存边    NEXT[cont]=first[a];    first[a]=cont;    cont++;}void BellmanDU()//Bellman队列优化{    queue<int> q;    memset(dis,-1,sizeof(dis));//标记从起点到各个点的最短路    memset(vis,0,sizeof(vis));//标记点是否在队列里    q.push(S);    vis[S]=1;    dis[S]=0;    while(!q.empty())    {        int s=q.front();        q.pop();        vis[s]=0;        int k=first[s];        while(k!=-1)//遍历以s为起点的所有点        {            if(dis[v[k]]==-1||(dis[v[k]]>dis[u[k]]+w[k]))//是否松弛成功            {                dis[v[k]]=dis[u[k]]+w[k];                if(!vis[v[k]])//该点是否在队列里                {                    vis[v[k]]=1;                    q.push(v[k]);//入队                }            }            k=NEXT[k];//下一条边        }    }}void Bellman()//Bellman算法{    memset(dis,-1,sizeof(dis));//初始化    dis[S]=0;    for(int i=1; i<=N-1; i++) //松弛N-1次        for(int j=1; j<=M; j++) //判断每条边            if(dis[v[j]]==-1||dis[v[j]]>dis[u[j]]+w[j])                dis[v[j]]=dis[u[j]]+w[j];    /*flag=0;//检测负权回路    for(int j=1;j<=M;j++)        if(dis[v[j]]>dis[u[j]]+w[j])        flag=1;        if(flag)            printf("此图含有负权回路\n");*/}int main(){    while(~scanf("%d%d%d%d",&N,&M,&S,&T))//点,边,起点,终点    {        memset(first,-1,sizeof(first));//first存以下标为起点的第一条边的标号,标号为u,v,w三个数组的下标        cont=1;        for(int i=0; i<M; i++)        {            int a,b,c;            scanf("%d%d%d",&a,&b,&c);            buildmap(a,b,c);            buildmap(b,a,c);//双向图            //有可能有重边        }        Bellman();//BellmanDU();        printf("%d\n",dis[T]);    }}

0 0
原创粉丝点击