zoukankan      html  css  js  c++  java
  • SGU326Perspective(网络流量的最大流量)(经典赛车模型)

    职务地址:http://acm.sgu.ru/problem.php?

    contest=0&problem=326

    额,这题读错题了。。。又WA了好长时间。。。坚持不看题解也挺浪费时间的。。早点看题解不自己憋着就能早就发现这个傻逼错误了。。。

    我的错误是把第三行输入的值误觉得是仅仅有跨赛区的比赛了。事实上后面的括号中非常明显写着包含同赛区的比赛。

    。可是我不认识。。

    又懒得翻译。。于是这个傻逼错误就诞生了。。

    这题有一种贪心的思想。就是让队伍1的跨赛区比赛尽可能获胜,其它队伍的跨赛区比赛尽可能输。然后算出此时队伍1与其它队伍的积分差值。

    建图方法是建立一个源点与一个汇点,把每一场比赛单独看作一个单位。将比赛与源点连边。权值为这场比赛的比赛数。将每场比赛与比赛两方连边,这个权值能够为无限大,仅仅要大于比赛数就能够。

    最后将每一个队与汇点连边,权值为这个队要想不超过队伍1的最大可能分数,即与队伍1的积分差值。

    最后求最大流是否满流。

    代码例如以下:

    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    #include <ctype.h>
    #include <queue>
    #include <map>
    #include<algorithm>
    using namespace std;
    const int INF=0x3f3f3f3f;
    int head[500], souce, sink, nv, cnt;
    int cur[500], num[500], d[500], q[500], p[50], mp[30][30], pre[500];
    struct node
    {
        int u, v, cap, next;
    } edge[1000000];
    void add(int u, int v, int cap)
    {
        edge[cnt].v=v;
        edge[cnt].cap=cap;
        edge[cnt].next=head[u];
        head[u]=cnt++;
    
        edge[cnt].v=u;
        edge[cnt].cap=0;
        edge[cnt].next=head[v];
        head[v]=cnt++;
    }
    void bfs()
    {
        memset(num,0,sizeof(num));
        memset(d,-1,sizeof(d));
        int f1=0, f2=0, i;
        d[sink]=0;
        num[0]=1;
        q[f1++]=sink;
        while(f1>=f2)
        {
            int u=q[f2++];
            for(i=head[u];i!=-1;i=edge[i].next)
            {
                int v=edge[i].v;
                if(d[v]==-1)
                {
                    d[v]=d[u]+1;
                    num[d[v]]++;
                    q[f1++]=v;
                }
            }
        }
    }
    int isap()
    {
        memcpy(cur,head,sizeof(cur));
        bfs();
        int flow=0, u=pre[souce]=souce, i;
        while(d[souce]<nv)
        {
            if(u==sink)
            {
                int f=INF, pos;
                for(i=souce;i!=sink;i=edge[cur[i]].v)
                {
                    if(f>edge[cur[i]].cap)
                    {
                        f=edge[cur[i]].cap;
                        pos=i;
                    }
                }
                for(i=souce;i!=sink;i=edge[cur[i]].v)
                {
                    edge[cur[i]].cap-=f;
                    edge[cur[i]^1].cap+=f;
                }
                flow+=f;
                u=pos;
            }
            for(i=cur[u];i!=-1;i=edge[i].next)
            {
                if(d[edge[i].v]+1==d[u]&&edge[i].cap)
                    break;
            }
            if(i!=-1)
            {
                cur[u]=i;
                pre[edge[i].v]=u;
                u=edge[i].v;
            }
            else
            {
                if(--num[d[u]]==0) break;
                int mind=nv;
                for(i=head[u];i!=-1;i=edge[i].next)
                {
                    if(mind>d[edge[i].v]&&edge[i].cap)
                    {
                        mind=d[edge[i].v];
                        cur[u]=i;
                    }
                }
                d[u]=mind+1;
                num[d[u]]++;
                u=pre[u];
            }
        }
        return flow;
    }
    int main()
    {
        int n, x, i, j, flag=0, s=0, sum=0, ss;
        memset(head,-1,sizeof(head));
        cnt=0;
        scanf("%d",&n);
        for(i=1; i<=n; i++)
            scanf("%d",&p[i]);
        scanf("%d",&x);
        p[1]+=x;
        for(i=1; i<n; i++)
            scanf("%d",&x);
        for(i=2; i<=n; i++)
        {
            if(p[i]>p[1])
            {
                flag=1;
                break;
            }
        }
        if(flag)
        {
            printf("NO
    ");
        }
        else
        {
            for(i=1; i<=n; i++)
            {
                for(j=1; j<=n; j++)
                {
                    scanf("%d",&mp[i][j]);
                    if(mp[i][j]&&i!=1&&j!=1&&j<i)
                    {
                        s++;
                        add(0,s,mp[i][j]);
                        sum+=mp[i][j];
                    }
                }
            }
            //for(i=1;i<=n;i++)
              //  p[1]+=mp[1][i];
            souce=0;
            sink=s+n+1;
            nv=sink+1;
            ss=0;
            for(i=2;i<=n;i++)
            {
                add(s+i,sink,p[1]-p[i]);
                for(j=2;j<i;j++)
                {
                    if(mp[i][j])
                    {
                        ss++;
                        add(ss,i+s,mp[i][j]);
                        add(ss,j+s,mp[i][j]);
                    }
                }
            }
            x=isap();
            if(x>=sum)
                printf("YES
    ");
            else
                printf("NO
    ");
        }
        return 0;
    }
    


    版权声明:本文博主原创文章,博客,未经同意不得转载。

  • 相关阅读:
    Androidstudio 使用git插件提交代码
    androidstudio上传代码到git上
    tcpdump的简单使用
    使用nmap工具查询局域网某个网段正在使用的ip地址
    网段的划分
    jenkins配置源码管理git
    shell条件测试test
    shell简单用法笔记(shell中数值运算)二
    shell简单用法笔记(一)
    如何解决audiodg占用内存高(停止与重启audiodg服务)
  • 原文地址:https://www.cnblogs.com/hrhguanli/p/4807484.html
Copyright © 2011-2022 走看看