• 圆桌问题(最大流)


    圆桌问题

    https://www.luogu.org/problemnew/show/P3254

    题目描述

    假设有来自m 个不同单位的代表参加一次国际会议。每个单位的代表数分别为ri (i =1,2,……,m)。

    会议餐厅共有n 张餐桌,每张餐桌可容纳ci (i =1,2,……,n)个代表就餐。

    为了使代表们充分交流,希望从同一个单位来的代表不在同一个餐桌就餐。试设计一个算法,给出满足要求的代表就餐方案。

    对于给定的代表数和餐桌数以及餐桌容量,编程计算满足要求的代表就餐方案。

    输入输出格式

    输入格式:

    第1 行有2 个正整数m 和n,m 表示单位数,n 表示餐桌数,1<=m<=150, 1<=n<=270。

    第2 行有m 个正整数,分别表示每个单位的代表数。

    第3 行有n 个正整数,分别表示每个餐桌的容量。

    输出格式:

    如果问题有解,第1 行输出1,否则输出0。接下来的m 行给出每个单位代表的就餐桌号。如果有多个满足要求的方案,只要输出1 个方案。

    输入输出样例

    输入样例#1: 
    4 5
    4 5 3 5
    3 5 2 6 4
    输出样例#1: 
    1
    1 2 4 5
    1 2 3 4 5
    2 4 5
    1 2 3 4 5

    源点拉一条容量为aa[i]的边到左边的点,左边的点拉容量为1的边到右边的点,右边的点拉容量为bb[i]的边到汇点
      1 #include<iostream>
      2 #include<cstring>
      3 #include<string>
      4 #include<cmath>
      5 #include<cstdio>
      6 #include<algorithm>
      7 #include<queue>
      8 #include<vector>
      9 #include<set>
     10 #define maxn 1000005
     11 #define MAXN 1000005
     12 #define mem(a,b) memset(a,b,sizeof(a))
     13 const int N=1000005;
     14 const int M=1000005;
     15 const int INF=0x3f3f3f3f;
     16 using namespace std;
     17 int n;
     18 struct Edge{
     19     int v,next;
     20     int cap,flow;
     21 }edge[MAXN*6];//注意这里要开的够大。。不然WA在这里真的想骂人。。问题是还不报RE。。
     22 int cur[MAXN],pre[MAXN],gap[MAXN],path[MAXN],dep[MAXN];
     23 int cnt=0;//实际存储总边数
     24 void isap_init()
     25 {
     26     cnt=0;
     27     memset(pre,-1,sizeof(pre));
     28 }
     29 void isap_add(int u,int v,int w)//加边
     30 {
     31     edge[cnt].v=v;
     32     edge[cnt].cap=w;
     33     edge[cnt].flow=0;
     34     edge[cnt].next=pre[u];
     35     pre[u]=cnt++;
     36 }
     37 void add(int u,int v,int w){
     38     isap_add(u,v,w);
     39     isap_add(v,u,0);
     40 }
     41 bool bfs(int s,int t)//其实这个bfs可以融合到下面的迭代里,但是好像是时间要长
     42 {
     43     memset(dep,-1,sizeof(dep));
     44     memset(gap,0,sizeof(gap));
     45     gap[0]=1;
     46     dep[t]=0;
     47     queue<int>q;
     48     while(!q.empty())
     49     q.pop();
     50     q.push(t);//从汇点开始反向建层次图
     51     while(!q.empty())
     52     {
     53         int u=q.front();
     54         q.pop();
     55         for(int i=pre[u];i!=-1;i=edge[i].next)
     56         {
     57             int v=edge[i].v;
     58             if(dep[v]==-1&&edge[i^1].cap>edge[i^1].flow)//注意是从汇点反向bfs,但应该判断正向弧的余量
     59             {
     60                 dep[v]=dep[u]+1;
     61                 gap[dep[v]]++;
     62                 q.push(v);
     63                 if(v==s)//感觉这两句优化加了一般没错,但是有的题可能会错,所以还是注释出来,到时候视情况而定
     64                 break;
     65             }
     66         }
     67     }
     68     return dep[s]!=-1;
     69 }
     70 int isap(int s,int t)
     71 {
     72     if(!bfs(s,t))
     73     return 0;
     74     memcpy(cur,pre,sizeof(pre));
     75     //for(int i=1;i<=n;i++)
     76     //cout<<"cur "<<cur[i]<<endl;
     77     int u=s;
     78     path[u]=-1;
     79     int ans=0;
     80     while(dep[s]<n)//迭代寻找增广路,n为节点数
     81     {
     82         if(u==t)
     83         {
     84             int f=INF;
     85             for(int i=path[u];i!=-1;i=path[edge[i^1].v])//修改找到的增广路
     86                 f=min(f,edge[i].cap-edge[i].flow);
     87             for(int i=path[u];i!=-1;i=path[edge[i^1].v])
     88             {
     89                 edge[i].flow+=f;
     90                 edge[i^1].flow-=f;
     91             }
     92             ans+=f;
     93             u=s;
     94             continue;
     95         }
     96         bool flag=false;
     97         int v;
     98         for(int i=cur[u];i!=-1;i=edge[i].next)
     99         {
    100             v=edge[i].v;
    101             if(dep[v]+1==dep[u]&&edge[i].cap-edge[i].flow)
    102             {
    103                 cur[u]=path[v]=i;//当前弧优化
    104                 flag=true;
    105                 break;
    106             }
    107         }
    108         if(flag)
    109         {
    110             u=v;
    111             continue;
    112         }
    113         int x=n;
    114         if(!(--gap[dep[u]]))return ans;//gap优化
    115         for(int i=pre[u];i!=-1;i=edge[i].next)
    116         {
    117             if(edge[i].cap-edge[i].flow&&dep[edge[i].v]<x)
    118             {
    119                 x=dep[edge[i].v];
    120                 cur[u]=i;//常数优化
    121             }
    122         }
    123         dep[u]=x+1;
    124         gap[dep[u]]++;
    125         if(u!=s)//当前点没有增广路则后退一个点
    126         u=edge[path[u]^1].v;
    127      }
    128      return ans;
    129 }
    130 
    131 int aa[350];
    132 int bb[350];
    133 
    134 int main(){
    135     int m,s,t;
    136     cin>>m>>n;
    137     int a,b,c;
    138     isap_init();
    139     int sum=0;
    140     for(int i=1;i<=m;i++){
    141         cin>>aa[i];///代表数量
    142         sum+=aa[i];
    143     }
    144     for(int i=1;i<=n;i++){
    145         cin>>bb[i];///桌的容量
    146     }
    147     for(int i=1;i<=m;i++){
    148         for(int j=1;j<=n;j++){
    149             add(i,m+j,1);
    150         }
    151     }
    152     s=0,t=n+m+1;
    153     for(int i=1;i<=m;i++){
    154         add(s,i,aa[i]);
    155     }
    156     for(int i=1;i<=n;i++){
    157         add(m+i,t,bb[i]);
    158     }
    159     n=n+m+2;
    160     int ans=isap(s,t);
    161     if(ans==sum){
    162         cout<<1<<endl;
    163         for(int i=1;i<=m;i++){
    164             for(int j=pre[i];~j;j=edge[j].next){
    165                 if(edge[j].flow==1){
    166                     cout<<edge[j].v-m<<" ";
    167                 }
    168             }
    169             cout<<endl;
    170         }
    171     }
    172     else{
    173         cout<<0<<endl;
    174     }
    175 }
    View Code
  • 相关阅读:
    oracle(Xe)数据库远程连接需修改配置参数
    oracl 权限循环查询
    控件网站
    java常用类(1)
    关于webdriver和谷歌浏览器的那些事
    2020年第27周,24.75h,完成计算智能/物联网/数据挖掘大作业
    2020年第26周,24.75h,计算智能的大小作业
    2020年第25周,25.5h,随机过程考试、report和计算智能作业
    2020年24周,11.75h,以完成作业和考试为主,看了一点点论文
    2020年第23周,11h,努力完成课程作业
  • 原文地址:https://www.cnblogs.com/Fighting-sh/p/9829657.html
Copyright © 2020-2023  润新知