图论基础算法

dijkstral堆优化算法

struct node
{
    int u,d;
    node(int u=0,int d=0):u(u),d(d){}
    bool operator < (const node& t) const{ return d>t.d; }
};
struct edge
{
    int u,v,w;
    edge(int u=0,int v=0,int w=0):u(u),v(v),w(w){}
};
vector<edge> G[maxn];
priority_queue<node> que;
int N,D[maxn];
bool vis[maxn];
void Dijkstra(int s)
{
    while(!que.empty()) que.pop();
    for(int i=0;i<=N;i++) D[i]=INF;
    D[s]=0;
    memset(vis,false,sizeof(vis));
    que.push(node(s,0));
    while(!que.empty())
    {
        node t=que.top(); que.pop();
        int u=t.u;
        if(vis[u]) continue;
        vis[u]=true;
        int Size=G[u].size();
        for(int i=0;i<Size;i++)
        {
            edge& e=G[u][i];
            int v=e.v,w=e.w;
            if(D[v]>D[u]+w)
            {
                D[v]=D[u]+w;
                que.push(node(v,D[v]));
            }
        }
    }
}
View Code

2SAT紫书模板

struct TwoSAT
{
    int n;
    vector<int> G[maxn*2];
    bool mark[maxn*2];
    int S[maxn*2],c;
    bool dfs(int u)
    {
        if(mark[u^1]) return false; //对立面为真,矛盾
        if(mark[u]) return true;
        mark[u]=true;
        S[c++]=u; //记录下来方便后面修改
        int Size=G[u].size();
        for(int i=0;i<Size;i++)
        {
            int v=G[u][i];
            if(!dfs(v)) return false;
        }
        return true;
    }
    void init(int nn)
    {
        n=nn;
        for(int i=0;i<=2*n;i++) G[i].clear(),mark[i]=false;
    }
    void AddNode(int x,int xval,int y,int yval)
    {
        x=x*2+xval;
        y=y*2+yval;
        G[x^1].push_back(y);
        G[y^1].push_back(x);
    }
    bool solve()
    {
        for(int i=0;i<n*2;i+=2)
            if(!mark[i]&&!mark[i+1]) //都没有访问过
            {
                c=0;
                if(!dfs(i)) //为假全部翻转
                {
                    while(c>0) mark[S[--c]]=false;
                    if(!dfs(i+1)) return false; //都矛盾则无解
                }
            }
        return true;
    }
};
View Code

2SAT的Tarjan写法

struct TwoSAT
{
    vector<int> G[2*maxn];
    int dfn[2*maxn],low[2*maxn];
    int KK[2*maxn],b[2*maxn];
    bool vis[2*maxn];
    int scc,top,id,n;
    void init(int nn=maxn-1)
    {
        n=nn;
        for(int i=0;i<=2*n;i++)
        {
            G[i].clear();
            dfn[i]=0;
            vis[i]=false;
        }
        scc=top=id=0;
    }
    void AddEdge(int u,int d1,int v,int d2)
    {
        u=u*2+d1;
        v=v*2+d2;
        G[u].push_back(v);
    }
    void Tarjan(int u)
    {
        dfn[u]=low[u]=++id;
        vis[u]=true;
        KK[++top]=u;
        int v,Size=G[u].size();
        for(int i=0;i<Size;i++)
        {
            v=G[u][i];
            if(!dfn[v])
            {
                Tarjan(v);
                low[u]=min(low[u],low[v]);
            }
            else if(vis[v]) low[u]=min(low[u],dfn[v]);
        }
        if(dfn[u]==low[u])
        {
            scc++;
            while(true)
            {
                v=KK[top--];
                vis[v]=false;
                b[v]=scc;
                if(v==u) break;
            }
        }
    }
    bool judge()
    {
        for(int i=0;i<2*n;i++) if(!dfn[i]) Tarjan(i);
        for(int i=0;i<2*n;i+=2) if(b[i]==b[i+1]) return false;
        return true;
    }
}sat;
View Code

第K短路

#include<cstdio>
#include<cstring>
#include<string>
#include<queue>
#include<algorithm>
using namespace std;
const int INF=1e8;
const int maxn=1001;
int N,M,be,en,K;
struct edge
{
    int v,c,next;
    edge(int v=0,int c=0):v(v),c(c){}
}E[2][maxn*100];
int head[2][maxn],eid;
int dist[maxn];
int cnt[maxn];
struct node
{
    int v,d;
    node(int v=0,int d=0):v(v),d(d){}
    bool operator < (const node& t) const
    { return d+dist[v]>t.d+dist[t.v]; }
};
priority_queue<node> que;
void Dij(int st)
{
    memset(cnt,0,sizeof(cnt));
    for(int i=0;i<=N;i++) dist[i]=INF;
    dist[st]=0;
    while(!que.empty()) que.pop();
    que.push(node(st,0));
    while(!que.empty())
    {
        node t=que.top(); que.pop();
        int u=t.v;
        if(cnt[u]) continue;
        cnt[u]=1;
        for(int i=head[1][u];i!=-1;i=E[1][i].next)
        {
            int v=E[1][i].v,c=E[1][i].c;
            if(dist[v]>dist[u]+c)
            {
                dist[v]=dist[u]+c;
                que.push(node(v,0));
            }
        }
    }
}
int solve(int st)
{
    memset(cnt,0,sizeof(cnt));
    while(!que.empty()) que.pop();
    que.push(node(st,0));
    while(!que.empty())
    {
        node t=que.top(); que.pop();
        int u=t.v,d=t.d;
        cnt[u]++;
        if(cnt[u]==K) return d+dist[u];
        for(int i=head[0][u];i!=-1;i=E[0][i].next)
        {
            int v=E[0][i].v,c=E[0][i].c;
            if(cnt[v]<=K) que.push(node(v,d+c));
        }
    }
    return -1;
}
int main()
{
    while(scanf("%d%d",&N,&M)!=EOF)
    {
        memset(head,-1,sizeof(head));
        int u,v,c;
        eid=0;
        while(M--)
        {
            scanf("%d%d%d",&u,&v,&c);
            E[0][++eid]=edge(v,c);
            E[0][eid].next=head[0][u];
            head[0][u]=eid;
            E[1][eid]=edge(u,c);
            E[1][eid].next=head[1][v];
            head[1][v]=eid;
        }
        scanf("%d%d%d",&be,&en,&K);
        Dij(en);
        if(dist[be]==INF){ printf("-1
"); continue; }
        if(be==en) K++;
        printf("%d
",solve(be));
    }
    return 0;
}
View Code

最优比例生成树

#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
const int maxn=105;
const int maxm=10005;
int N,M;
double low,up,mid;
struct edge
{
    int u,v,w,c;
    edge(int u=0,int v=0,int w=0,int c=0)
    :u(u),v(v),w(w),c(c){}
    bool operator < (const edge& t) const
    {
        return (double)(w-mid*c)<(double)(t.w-mid*t.c);
    }
}E[maxm];
int d[maxn];
int root(int a){ return d[a]==a?a:d[a]=root(d[a]); }
double Kruskal()
{
    sort(E,E+M);
    for(int i=0;i<=N;i++) d[i]=i;
    int step=0;
    double ret=0.0;
    for(int i=0;i<M;i++)
    {
        edge& e=E[i];
        int u=e.u,v=e.v,w=e.w,c=e.c;
        int ra=root(u);
        int rb=root(v);
        if(ra==rb) continue;
        d[rb]=ra;
        ret+=(double)(w-mid*c);
        step++;
        if(step==N-1) break;
    }
    return ret;
}
double solve()
{
    low=0,up=10000;
    int cnt=150;
    while(cnt--)
    {
        mid=(low+up)/2;
        if(Kruskal()>0) low=mid;
        else up=mid;
    }
    return low;
}
int main()
{
    while(scanf("%d%d",&N,&M)!=EOF)
    {
        int u,v,w,c;
        for(int i=0;i<M;i++)
        {
            scanf("%d%d%d%d",&u,&v,&w,&c);
            E[i]=edge(u,v,w,c);
        }
        printf("%.4f
",solve());
    }
    return 0;
}
View Code

Prim算法

int prim(int st)
{
    for(int i=0;i<maxn;i++)  D[i]=INF;
    D[st]=0;
    memset(vis,false,sizeof(vis));
    int ret=0;
    for(int i=0;i<N;i++)
    {
        int pos=-1;
        for(int j=0;j<N;j++)  if(!vis[j]&&(pos==-1||D[j]<D[pos]))  pos=j;
        if(pos==-1)  break;
        vis[pos]=true;
        ret+=D[pos];
        for(int j=0;j<N;j++)  D[j]=min(D[j],dist[pos][j]);
    }
    return ret;
}
View Code

Bellman算法

int dist[155];
bool bellman()
{
    memset(dist,0,sizeof(dist));
    for(int i=1;i<=N;i++)
        for(int j=0;j<M;j++)
        {
            edge& e=save[j];
            if(dist[e.to]>dist[e.from]+e.weight)  dist[e.to]=dist[e.from]+e.weight;
        }
    for(int j=0;j<M;j++)
    {
        {
            edge& e=save[j];
            if(dist[e.to]>dist[e.from]+e.weight)  return false;
        }
    }
    return true;

}
View Code

Dijkstra算法

int dist[35][35],vis[35],D[35];
int dijkstra(int op)
{
    memset(vis,0,sizeof(vis));
    for(int i=1;i<=N;i++)  D[i]=INF;
    vis[op]=1;
    D[1]=0;
    while(true)
    {
        int pos=-1;
        for(int i=1;i<=N;i++)  if(!vis[i]&&(pos==-1||D[i]<D[pos]))  pos=i;
        if(pos==-1)  break;
        vis[pos]=1;
        for(int i=1;i<=N;i++)  D[i]=min(D[i],D[pos]+dist[i][pos]);
    }
    return D[N];
}
View Code

spfa算法

double D[105];
bool inq[105];
bool spfa(int start)
{
     for(int i=1;i<=N;i++)  D[i]=dbinf;
     memset(inq,false,sizeof(inq));
     D[start]=0.0;
     queue<int> que;
     que.push(start);
     while(!que.empty())
     {
         int now=que.front();  que.pop();
         inq[now]=false;
         for(int i=1;i<=N;i++)
            if(i!=now&&dist[i][now]<=10.0&&D[i]>D[now]+dist[i][now])
         {
             D[i]=D[now]+dist[i][now];
             if(!inq[i])  { inq[i]=true; que.push(i); }
         }
     }
     for(int i=1;i<=N;i++)
     {
         if(D[i]>10000000.0)  return false;
         ans=max(ans,D[i]);
     }
     return true;
}
View Code
原文地址:https://www.cnblogs.com/wust-ouyangli/p/5778531.html