• POJ 1860&&3259&&1062&&2253&&1125&&2240


      六道烦人的最短路(然而都是水题)

      我也不准备翻译题目了(笑)

      一些是最短路的变形(比如最长路,最短路中的最长边,判环),还有一些就是裸题了。

      1860:找环,只需要把SPFA的松弛条件改一下即可,这里打的是BFS的。如果一个点入队次数大于n次,那么一定有环存在。

      CODE

    #include<cstdio>
    #include<cstring>
    using namespace std;
    typedef double DB;
    const int N=105;
    struct data
    {
        int to,next;
        DB r,c;
    }e[N*2];
    int head[N],q[N*N*10],t[N],n,m,s,i,x,y,k=0;
    DB dis[N],v,r,c;
    bool vis[N];
    inline void add(int x,int y,DB r,DB c)
    {
        e[++k].to=y; e[k].r=r; e[k].c=c; e[k].next=head[x]; head[x]=k;
    }
    int main()
    {
        memset(head,-1,sizeof(head));
        memset(e,-1,sizeof(e));
        scanf("%d%d%d%lf",&n,&m,&s,&v);
        for (i=1;i<=m;++i)
        {
            scanf("%d%d%lf%lf",&x,&y,&c,&r);
            add(x,y,r,c);
            scanf("%lf%lf",&c,&r);
            add(y,x,r,c);
        }
        int H=0,T=1;
        dis[s]=v; q[1]=s; vis[s]=t[s]=1;
        while (H<T)
        {
            int now=q[++H];
            vis[now]=0;
            if (t[now]>n) { puts("YES"); return 0; }
            for (i=head[now];i!=-1;i=e[i].next)
            if (dis[e[i].to]<(dis[now]-e[i].r)*e[i].c)
            {
                dis[e[i].to]=(dis[now]-e[i].r)*e[i].c;
                if (!vis[e[i].to])
                {
                    q[++T]=e[i].to;
                    vis[e[i].to]=1;
                    t[e[i].to]++;
                } 
            }
        }
        puts("NO");
        return 0;
    }

      3259:几乎相同的SPFA判负环,这里写了DFS(判环比BFS的快)

      CODE

    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int N=10005;
    struct data
    {
        int to,next,v;
    }e[N];
    int t,n,m,w,i,x,y,z,k,dis[N],vis[N],head[N];
    bool flag;
    inline void read(int &x)
    {
        x=0; char ch=getchar();
        while (ch<'0'||ch>'9') ch=getchar();
        while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    }
    inline void add(int x,int y,int z)
    {
        e[++k].to=y; e[k].v=z; e[k].next=head[x]; head[x]=k;
    }
    inline void SPFA(int now)
    {
        vis[now]=1;
        if (flag) return;
        for (int i=head[now];i!=-1;i=e[i].next)
        if (dis[e[i].to]>dis[now]+e[i].v)
        {
            if (vis[e[i].to]) { flag=1; return; }
            dis[e[i].to]=dis[now]+e[i].v;
            SPFA(e[i].to);
        }
        vis[now]=0;
    }
    int main()
    {
        read(t);
        while (t--)
        {
            memset(e,-1,sizeof(e));
            memset(head,-1,sizeof(head));
            memset(vis,0,sizeof(vis));
            read(n); read(m); read(w);
            k=flag=0;
            for (i=1;i<=m;++i)
            {
                read(x); read(y); read(z);
                add(x,y,z); add(y,x,z);
            }
            for (i=1;i<=w;++i)
            {
                read(x); read(y); read(z);
                add(x,y,-z);
            }
            for (i=1;i<=n;++i)
            {
                if (flag) break;
                memset(dis,0,sizeof(dis));
                SPFA(i);
            }
            if (flag) puts("YES"); else puts("NO");
        }
        return 0;
    }

      1062:枚举+SPFA,感觉SPFA写起来比DJ舒服,DJ还要开个堆。

      对于等级的限制我们只需要枚举等级的左右端点即可。

      CODE

    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int N=105;
    struct data
    {
        int to,next,v;
    }e[N*N];
    int head[N],dis[N],vis[N],lev[N],v[N],q[N*10],t,n,c,k,i,j,num,p,l,r,ans=1e9;
    inline void read(int &x)
    {
        x=0; char ch=getchar();
        while (ch<'0'||ch>'9') ch=getchar();
        while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    }
    inline void add(int x,int y,int z)
    {
        e[++k].to=y; e[k].v=z; e[k].next=head[x]; head[x]=k;
    }
    inline int min(int a,int b)
    {
        return a<b?a:b;
    }
    inline int SPFA(int s)
    {
        memset(dis,63,sizeof(dis));
        dis[s]=0; vis[s]=1; q[1]=s;
        int H=0,T=1,res=1e9;
        while (H<T)
        {
            int now=q[++H];
            vis[now]=0;
            for (int i=head[now];i!=-1;i=e[i].next)
            if (lev[e[i].to]>=l&&lev[e[i].to]<=r)
            if (dis[e[i].to]>dis[now]+e[i].v)
            {
                dis[e[i].to]=dis[now]+e[i].v;
                if (!vis[e[i].to]) q[++T]=e[i].to,vis[e[i].to]=1;
            }
        }
        for (int i=1;i<=n;++i)
        res=min(res,dis[i]+v[i]);
        return res;
    }
    int main()
    {
        memset(e,-1,sizeof(e));
        memset(head,-1,sizeof(head));
        read(t); read(n);
        for (i=1;i<=n;++i)
        {
            read(v[i]); read(lev[i]); read(c);
            for (j=1;j<=c;++j)
            {
                read(num); read(p);
                add(i,num,p);
            }
        }
        for (i=1;i<=t+1;++i)
        {
            l=lev[1]+i-1-t; r=lev[1]+i-1;
            ans=min(ans,SPFA(1));
        }
        printf("%d",ans);
        return 0;
    }

      2253:求最短路中的最长边—>写DJ,改松弛条件—>炸了,改写最小生成树(Kruskal)找最短边

      其实图论题重在建模!

      CODE

    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    typedef double DB;
    const int N=205,INF=1e9;
    struct data
    {
        int x,y;
        DB s;
    }e[N*N];
    int father[N],x[N],y[N],c,n,i,j,k;
    DB ans;
    inline void read(int &x)
    {
        x=0; char ch=getchar();
        while (ch<'0'||ch>'9') ch=getchar();
        while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    }
    inline DB calc(int a,int b)
    {
        return sqrt((double)(x[a]-x[b])*(x[a]-x[b])+(double)(y[a]-y[b])*(y[a]-y[b]));
    }
    inline void add(int x,int y,DB z)
    {
        e[++k].x=x; e[k].y=y; e[k].s=z;
    }
    inline int comp(data a,data b)
    {
        return a.s<b.s;
    }
    inline int getfather(int k)
    {
        return father[k]==k?k:father[k]=getfather(father[k]);
    }
    int main()
    {
        for (;;)
        {
            read(n);
            if (!n) break;
            k=ans=0;
            for (i=1;i<=n;++i)
            read(x[i]),read(y[i]),father[i]=i;
            for (i=1;i<n;++i)
            for (j=i+1;j<=n;++j)
            add(i,j,calc(i,j)),add(j,i,calc(i,j));
            sort(e+1,e+k+1,comp);
            for (i=1;i<=k;++i)
            {
                int fx=getfather(e[i].x),fy=getfather(e[i].y);
                if (getfather(1)==getfather(2)) break;
                if (fx!=fy)
                {
                    father[fx]=fy;
                    ans=e[i].s;
                }
            }
            printf("Scenario #%d
    Frog Distance = %.3lf
    
    ",++c,ans);
        }
    }

      1125:最短路模板题,不过要枚举起点再跑SPFA(话说这是Floyd能解决的事,但我发现我好像不会Floyd了)

      CODE

    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int N=105,INF=1e9;
    struct data
    {
        int to,next,v;
    }e[N*N];
    int dis[N],head[N],q[N*N*10],n,i,j,m,k,x,y,ans,num;
    bool vis[N];
    inline void read(int &x)
    {
        x=0; char ch=getchar();
        while (ch<'0'||ch>'9') ch=getchar();
        while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    }
    inline void add(int x,int y,int z)
    {
        e[++k].to=y; e[k].v=z; e[k].next=head[x]; head[x]=k;
    }
    int main()
    {
        for (;;)
        {
            read(n);
            if (!n) break;
            ans=INF; num=k=0;
            memset(e,-1,sizeof(e));
            memset(head,-1,sizeof(head));
            for (i=1;i<=n;++i)
            {
                read(m);
                for (j=1;j<=m;++j)
                {
                    read(x); read(y);
                    add(i,x,y);
                }
            }
            for (i=1;i<=n;++i)
            {
                for (j=1;j<=n;++j)
                dis[j]=INF;
                memset(vis,0,sizeof(vis));
                dis[i]=0; vis[i]=1; q[1]=i;
                int H=0,T=1;
                while (H<T)
                {
                    int now=q[++H];
                    vis[now]=0;
                    for (j=head[now];j!=-1;j=e[j].next)
                    {
                        if (dis[e[j].to]>dis[now]+e[j].v)
                        {
                            dis[e[j].to]=dis[now]+e[j].v;
                            if (!vis[e[j].to]) q[++T]=e[j].to,vis[e[j].to]=1;
                        }
                    }
                }
                int res=0;
                for (j=1;j<=n;++j)
                if (dis[j]>res) res=dis[j];
                if (res<ans) ans=res,num=i;
            }
            if (ans==INF) puts("disjoint"); else printf("%d %d
    ",num,ans);
        }
    }

      2240:同样的货币兑换,也是找环的过程。这里对于字符串懒得写hash了,直接开了map

      CODE

    #include<cstdio>
    #include<map>
    #include<string>
    #include<cstring>
    #include<iostream>
    using namespace std;
    typedef double DB;
    const int N=35;
    map <string,int> hash;
    struct data
    {
        int to,next;
        DB v;
    }e[N*N];
    string s1,s2;
    DB dis[N],v;
    int head[N],n,i,k,m,t;
    bool vis[N],flag;
    inline void read(int &x)
    {
        x=0; char ch=getchar();
        while (ch<'0'||ch>'9') ch=getchar();
        while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    }
    inline void add(int x,int y,DB z)
    {
        e[++k].to=y; e[k].v=z; e[k].next=head[x]; head[x]=k;
    }
    inline void SPFA(int now)
    {
        if (flag) return;
        vis[now]=1;
        for (int i=head[now];i!=-1;i=e[i].next)
        if (dis[e[i].to]<dis[now]*e[i].v)
        {
            if (vis[e[i].to]) { flag=1; return; }
            dis[e[i].to]=dis[now]*e[i].v;
            SPFA(e[i].to);
        }
        vis[now]=0;
    }
    int main()
    {
        for (;;)
        {
            read(n); 
            if (!n) break;
            memset(e,-1,sizeof(e));
            memset(head,-1,sizeof(head));
            k=flag=0;
            for (i=1;i<=n;++i)
            {    
                cin>>s1;
                hash[s1]=i;
            }
            read(m);
            for (i=1;i<=m;++i)
            {
                cin>>s1; scanf("%lf",&v); cin>>s2;
                add(hash[s1],hash[s2],v);
            }
            for (i=1;i<=n;++i)
            {
                if (flag) break;
                memset(dis,0,sizeof(dis));
                memset(vis,0,sizeof(vis));
                dis[i]=1;
                SPFA(i);
            }
            if (flag) printf("Case %d: Yes
    ",++t); else printf("Case %d: No
    ",++t);
        }
        return 0;
    }

      准备结束图论专题!

  • 相关阅读:
    Java实现 LeetCode 209 长度最小的子数组
    Java实现 蓝桥杯 图书排列(全排列)
    Java实现 蓝桥杯 图书排列(全排列)
    Java实现 蓝桥杯 图书排列(全排列)
    C++11 FAQ中文版--转
    rtsp交互命令简介及过程参数描述
    PS流格式
    经典系统windows xp sp3官方原版下载(附XP序列号)
    Darwin Streaming Server 简介
    jrtplib跨网络通讯NAT穿透问题解决方法
  • 原文地址:https://www.cnblogs.com/cjjsb/p/8544335.html
Copyright © 2020-2023  润新知