码迷,mamicode.com
首页 > 其他好文 > 详细

zoj3997网络流+数学

时间:2018-01-08 01:04:20      阅读:139      评论:0      收藏:0      [点我收藏+]

标签:cst   using   return   bsp   while   因子   nbsp   turn   数学   

 

题目大意就是每个人都有自己喜欢的座位编号,喜欢的编号是要x的倍数就好,(1<=x<=10)一共10种情况,每种情况的人的数目不一样。

给你一个n,代表有编号1-n这n个座位,问最多能满足多少人的喜爱要求。

 

lcm(1...10)=2520    x跟k*lcm+x的因子情况是一样的(对于1-10这十个数来说) 因为显然k*lcm可以提出x的任意因子,而若不是x的因子,后面+x提一下会出现小数显然就不满足情况了 ,所以是完全一样的。。那么只要预处理出来1-2520的因子情况就可以了。。

 

然后就随便跑跑网络流就可以了。。。。

 

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=111;
int q[N],head[N],tot,S,T,dis[N];
struct node{
    int to,next,w;
}e[N<<4];
void add(int u,int v,int w){
    e[tot].to=v;e[tot].next=head[u];e[tot].w=w;head[u]=tot++;
    e[tot].to=u;e[tot].next=head[v];e[tot].w=0;head[v]=tot++;
}
bool bfs(){
    int l=0,r=0;
    q[r++]=S;
    memset(dis,-1,sizeof(dis));
    dis[S]=0;
    while(l<r) {
        int u=q[l++];
        for(int i=head[u];~i;i=e[i].next){
            int v=e[i].to;
            if(dis[v]==-1&&e[i].w>0) {
                dis[v]=dis[u]+1;
                q[r++]=v;
                if(v==T) return true;
            }
        }
    }
    return false;
}
int dfs(int s,int low){
    if(!low||s==T) return low;
    int ans=low,a;
    for(int i=head[s];~i;i=e[i].next){
        int v=e[i].to;
        if(e[i].w>0&&dis[v]==dis[s]+1&&(a=dfs(v,min(ans,e[i].w)))) {
            ans-=a;
            e[i].w-=a;
            e[i^1].w+=a;
            if(!ans) return low;
        }
    }
    if(low==ans) dis[s]=-1;
    return low-ans;
}
int vis[1<<11],mark[2800],lim[88],p[88];
void init(){
    int cont=0;
    for(int i=0;i<2520;++i) {
        int S=0;
        for(int j=1;j<=10;++j)  if(i%j==0) S|=1<<j;
        if(!vis[S]) vis[S]=++cont,p[cont]=S;
        mark[i]=vis[S];
    }
}
int main(){
    init();
    int Ta,n,x;
    for(scanf("%d",&Ta);Ta--;){
        tot=0;
        memset(head,-1,sizeof(head));
        memset(lim,0,sizeof(lim));
        scanf("%d",&n);
        S=0,T=59;
        for(int i=0;i<2520;++i) {
            int now=n/2520;
            if(i&&n%2520>=i) ++now;
            lim[mark[i]]+=now;
        }
        for(int i=1;i<=48;++i) add(i+10,T,lim[i]);
        for(int i=1;i<=10;++i) {
            scanf("%d",&x);
            if(x) {
                add(S,i,x);
                for(int j=1;j<=48;++j) if(p[j]&(1<<i)) add(i,j+10,x);
            }
        }
        int ans=0;
        while(bfs()) ans+=dfs(S,1e9+7);
        printf("%d\n",ans);
    }
} 

 

zoj3997网络流+数学

标签:cst   using   return   bsp   while   因子   nbsp   turn   数学   

原文地址:https://www.cnblogs.com/mfys/p/8232644.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!