SGU326Perspective(网络流之最大流)(经典竞赛模型)

来源:互联网 发布:qq间谍软件 编辑:程序博客网 时间:2024/06/05 13:27

题目地址: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\n");    }    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\n");        else            printf("NO\n");    }    return 0;}


2 0
原创粉丝点击