poj2699 竞赛图+网络流

来源:互联网 发布:网络教育去哪里报名 编辑:程序博客网 时间:2024/06/07 07:51

这道题是个不错的题

【题意】

n个人比赛, 两两比,共n*(n-1), 赢得1分, n<=10(这给了我们枚举的暗示)

如果一个人打败了所有比自己分数高的人, 或者他本身就是分数最高的, 那么他就是

StrongKing

可能有多个Strong King, 现在按非降的顺序给你每个人的得分(不难道想到容量把), 问

Strong King最多能有几个

【解答】

一般遇到竞赛图,网络流的可能性较大,因为竞赛图中的条件都与点的度数有关。

建图:二分图,左边是人,右边是比赛,源点到人连容量为score[i]的边,汇点到比赛连

量为1的边。然后枚举答案ans,由于分数越高的人成为

strongking的可能性较大(我一开始没有意识到这点,还想用2^10的枚举),于是让后

ans人成为strongking,然后对这ans个人中的i,j,如果score[i]<score[j]则i像match[i]

[j]连容量为一的边。然后对剩余的比赛match[i][j],让i,j向点match[i][j]连容量为1的边。

当maxflow==n*(n-1)/2时,则ans为解

#include <iostream>#include <cstring>#include <string>#include <sstream>using namespace std;const int oo=200000;struct edge{       int x,y,f,next,op;}e[2000];int g[20],m[20][20],h[100],d[100],p[100],now[100],num[100],f[100];int n,s,t,tot,tt;void ins(int x,int y,int f){     e[++tot].x=x;e[tot].y=y;     e[tot].next=h[x];e[tot].f=f;     h[x]=tot;     e[++tot].x=y;e[tot].y=x;     e[tot].next=h[y];e[tot].f=0;     h[y]=tot;     e[tot].op=tot-1;e[tot-1].op=tot;}void build(int num){     tot=0;     int i,j;     memset(f,0,sizeof(f));     memset(h,0,sizeof(h));     for (i=1;i<=n;i++)         ins(s,i,g[i]);     for (i=1;i<=tt;i++)         ins(i+n,t,1);     for (i=n-num+1;i<=n;i++)         for (j=i+1;j<=n;j++)         if (g[j]>g[i])         {             f[m[i][j]]=1;             ins(i,m[i][j]+n,1);         }     for (i=1;i<=n;i++)         for (j=i+1;j<=n;j++)         if (!f[m[i][j]])         {             ins(i,m[i][j]+n,1);             ins(j,m[i][j]+n,1);         }}int isap(){    int flow=0,aug=oo,u,v,tmp,i,j,ff;    for (i=0;i<=t;i++)    {        d[i]=0;p[i]=-1;        num[i]=0;now[i]=h[i];    }    num[0]=t+1;u=s;    while (d[s]<t+1)    {          for (ff=0,i=now[u];i;i=e[i].next)          {              v=e[i].y;              if (e[i].f && d[u]==d[v]+1)              {                 ff=1;                 if (e[i].f<aug) aug=e[i].f;                 p[v]=i;now[u]=i;                 u=v;                 if (u==t)                 {                    flow+=aug;                    while (u!=s)                    {                          j=p[u];                          e[j].f-=aug;                          e[e[j].op].f+=aug;                          u=e[j].x;                    }                    aug=oo;                 }                 break;              }          }          if (ff) continue;          num[d[u]]--;          if (!num[d[u]]) return flow;          tmp=t+1;          for (i=h[u];i;i=e[i].next)          {              v=e[i].y;              if (e[i].f && d[v]<tmp)               {                 tmp=d[v];now[u]=i;              }          }          d[u]=tmp+1;          num[d[u]]++;          if (u!=s) u=e[p[u]].x;    }    return flow;}int main(){    freopen("pin.txt","r",stdin);    freopen("pou.txt","w",stdout);    char str[40];    int i,j,cc;    cin >> cc;    getchar();    while (cc--)    {          gets(str);          stringstream ss(str);          n=0;          while (ss >> j)                g[++n]=j;          tt=0;          for (i=1;i<=n;i++)              for (j=i+1;j<=n;j++)                  m[i][j]=++tt;          s=0;t=tt+n+1;          for (i=n;i>1;i--)          {              build(i);              if (isap()==(n*(n-1))/2) break;          }          cout << i << endl;    }    return 0;}



原创粉丝点击