zoukankan      html  css  js  c++  java
  • COJ 0503 比赛

    比赛
    难度级别:D; 运行时间限制:2000ms; 运行空间限制:51200KB; 代码长度限制:2000000B
    试题描述
    初三年级举办了一场篮球赛,共有N个班级参加。当WZJ知道了这件事情, 已经打完了若干场比赛(WZJ一直在写Fenwich套Treap),接下来还要进行M场比赛。第i场比赛的竞争班级是ai,bi,胜者得2分,负者得0 分,若平局则两班各得1分。为了让得分尽量平均,现在给出每个班级已经得到的分数si,与接下来M场比赛的安排,请你回答得分最多的班级的得分最少是多 少。
    输入
    第一行为两个正整数N,M。
    第二行为N个正整数si。
    接下来M行每行两个正整数ai,bi。
    输出
    请你回答得分最多的班级的得分最少是多少。
    输入示例
    5 3
    1 2 2 1 3
    1 5
    2 3
    4 5
    输出示例
    3
    其他说明
    第一场比赛1赢
    第二场比赛平局
    第三场比赛4赢
    则最后每个班级的得分都是3
    1<=N<=1000
    1<=M<=50000
    1<=si<=100
    1<=ai!=bi<=M

    题解:赤裸裸的网络流建模。

    首先看到破题口"得分最多的班级的得分最少是多少"先二分答案,将问题转化为"得分为point的方案是否可行"。怎么检查可行呢?(或者说怎么样才算可行)就是强制分配这么多的得分,如果每一场比赛都成功分配了两个队的分数我们就称之为"可行"(其实算是ISAP的处理流的办法:我们先模拟大量的流,不断地修正检查获得结果。以前我都不知道= =)。当然了,这么想是很辨证的,事实上一定会有其他的解法。

    继续,我们怎么分配分数并检查呢?仔细阅读这道题的特殊性:每场比赛一定会贡献两个积分,于是我们就用流来模拟积分的流动转移,最后在汇点处用容量卡每个队能获取分数的最大值。易知当且仅当每场比赛都分配出了两个积分(即最大流是比赛数量的两倍时)这样的方案是合法的。

    Ps二分图还是跑Dinic吧,ISAP快不了多少:

      1 #include<iostream>   
      2 #include<cstdio>
      3 #include<cmath>
      4 #include<algorithm>
      5 #include<queue>
      6 #include<cstring>
      7 using namespace std;
      8 const int maxn=52000+10,maxm=500000+10,inf=-1u>>1;
      9 struct ISAP{
     10     struct tedge{int x,y,w,next;}adj[maxm];int ms,fch[maxn];
     11     int d[maxn],s[maxn],cur[maxn],gap[maxn],n,top;
     12     void init(int n){
     13         this->n=n;ms=0;top=0;
     14         memset(d,-1,sizeof(d));
     15         memset(fch,-1,sizeof(fch));
     16         return;
     17     }
     18     void addedge(int u,int v,int w){
     19         adj[ms]=(tedge){u,v,w,fch[u]};fch[u]=ms++;
     20         adj[ms]=(tedge){v,u,0,fch[v]};fch[v]=ms++;
     21         return;
     22     }
     23     void bfs(){
     24         queue<int>Q;Q.push(n);d[n]=0;
     25         while(!Q.empty()){
     26             int u=Q.front();Q.pop();
     27             for(int i=fch[u];i!=-1;i=adj[i].next){
     28                 int v=adj[i].y;
     29                 if(d[v]==-1) d[v]=d[u]+1,Q.push(v);
     30             }
     31         } return;
     32     }
     33     int maxflow(int S,int T){
     34         n=T;bfs();int k=S,i,flow=0;
     35         for(i=0;i<=n;i++) cur[i]=fch[i],gap[d[i]]++;
     36         while(d[S]<n){
     37             if(k==n){
     38                 int mi=inf,pos;
     39                 for(i=0;i<top;i++) if(adj[s[i]].w<mi) mi=adj[s[i]].w,pos=i;
     40                 for(i=0;i<top;i++) adj[s[i]].w-=mi,adj[s[i]^1].w+=mi;
     41                 flow+=mi;top=pos;k=adj[s[top]].x;
     42             }
     43             for(i=cur[k];i!=-1;i=adj[i].next){
     44                 int v=adj[i].y;
     45                 if(adj[i].w&&d[k]==d[v]+1){cur[k]=i;k=v;s[top++]=i;break;}
     46             }
     47             if(i==-1){
     48                 int lim=n;
     49                 for(i=fch[k];i!=-1;i=adj[i].next){
     50                     int v=adj[i].y;
     51                     if(adj[i].w&&d[v]<lim) lim=d[v],cur[k]=i;
     52                 } if(--gap[d[k]]==0) break;
     53                 d[k]=lim+1;gap[d[k]]++;
     54                 if(k!=S) k=adj[s[--top]].x;
     55             }
     56         } return flow;
     57     }
     58 }sol;
     59 inline int read(){
     60     int x=0,sig=1;char ch=getchar();
     61     while(!isdigit(ch)){if(ch=='-') sig=-1;ch=getchar();}
     62     while(isdigit(ch)) x=10*x+ch-'0',ch=getchar();
     63     return x*=sig;
     64 }
     65 inline void write(int x){
     66     if(x==0){putchar('0');return;}if(x<0) putchar('-'),x=-x;
     67     int len=0,buf[15];while(x) buf[len++]=x%10,x/=10;
     68     for(int i=len-1;i>=0;i--) putchar(buf[i]+'0');return;
     69 }
     70 int n,m,a[maxn],b[maxn],p[maxn];
     71 bool check(int point){
     72     sol.init(n+m+3);
     73     int S=n+m+1,T=n+m+2;
     74     for(int i=1;i<=m;i++){
     75         sol.addedge(S,i,2);
     76         sol.addedge(i,a[i]+m,inf);
     77         sol.addedge(i,b[i]+m,inf);
     78     }
     79     for(int i=1;i<=n;i++) sol.addedge(i+m,T,point-p[i]);
     80     return sol.maxflow(S,T)==m<<1;
     81 }
     82 void init(){
     83     int L=0,R=0;n=read();m=read();
     84     for(int i=1;i<=n;i++) p[i]=read(),L=max(L,p[i]);
     85     for(int i=1;i<=m;i++) a[i]=read(),b[i]=read();
     86     R=L+(m<<1);
     87     while(L<R){
     88         int M=L+R>>1;
     89         if(check(M)) R=M;
     90         else L=M+1;
     91     }
     92     write(L);
     93     return;
     94 }
     95 void work(){
     96     return;
     97 }
     98 void print(){
     99     return;
    100 }
    101 int main(){
    102     init();work();print();return 0;
    103 }
  • 相关阅读:
    ie6-ie8中不支持opacity透明度的解决方法
    html5游戏-包围盒检测算法
    流媒体 8——因特网 tcp/ip
    流媒体 7——多媒体网络应用与交换
    流媒体 6——MPEG电视
    流媒体 5——MPEG声音
    流媒体 4——数字电视基础
    流媒体 3——彩色数字图像基础
    流媒体 2——数据无损压缩
    流媒体 1——概述+声音数字编码(pcm,dm......)
  • 原文地址:https://www.cnblogs.com/chxer/p/4545017.html
Copyright © 2011-2022 走看看