Annual Congress of MUD
Annual Congress of MUD
时间限制: 1 Sec 内存限制: 128 MB
题目描述
ACM is so popular that the event each year spans around 20 days. Each day, there will be a special gathering for MUD game designers to introduce their new games to the others.
Each player will usually spend a few days on the ACM site, and in-between will be invited in exactly one day to join this special gathering.
This year, ACM is held at your city, and your boss is an organiser, and he wants to find a best way to assign the players to these special gatherings (one player to one special gathering within his or her duration of stay), so that the maximum number of players among all gatherings is minimized.
Your boss is an extremely impatient guy. He wants to have a system that can tell the maximum number of players among all gatherings, in any best assignment, after each player enters his or her duration of stay. Your task is to help your boss develop such a system.
输入
输出
样例输入
3 3
1 1
1 1
1 1
3 3
1 2
2 3
1 1
3 3
1 2
1 2
1 2
0
样例输出
1 2 3
1
1 3
提示
1.The number of players joining the congress, N, is an integer with 1 ≤ N ≤ 10000.
2.The number of days, D, of the congress is an integer with 3 ≤ D ≤ 20.
3.The duration of stay, [xi , yi ], for the ith player to be keyed in your system, are pairs of integers with 1 ≤ xi ≤ yi ≤ D. This indicates that the ith player will stay from day xi (inclusive) to day yi (inclusive) on the ACM site.
题意:
嘉年华一共有D天,每个人在[xi,yi]这几天来玩,每天都有一次盛会,但一个人必须且仅能参加一次盛会,我们希望盛会人数最多的时候最少,设这个数为T,这样可以平衡盛会出席的人数。现在给定n个人按顺序申请来玩的时间,如果某个人申请来玩后T会增加,输出这个人的编号。
思路:
对于前i个人我们都要求出局部的最优解,并判断T是否增加(T一次最多增加1)。那么我们跑最大流即可。源点连向人,容量为1,人连向能去的那些天,容量为1,每天连向汇点,容量为盛会人数最多可能多少人。(ps:这个多少人如果我们只要求全局的最优,那么二分即可。)如果最大流不满流,就是最大流不等于当前的人数,连向汇点的边容量+1就一定能满流了。注意这样连边显然会TLE。我们修改构图,鉴于整个图容量为1的边很多,我们直接构造(D+1)*D/2个点表示区间,区间连向包含的天,容量为INF。那么我们每次加人,就相当于源点连向某个区间的边的容量+1。这样点的数量就相当少了。
一些优化:
上面的写法可能还是会TLE,需要一些优化。
1.每次跑最大流的时候,不需要重新构图跑,只要在残余网络上加上新建的边,再继续跑最大流就好了,每次都把这个流量累加起来。
2.因为每次跑最大流的时候我们就增加了一条路径,所以dinic算法的bfs函数会消耗很多时间,可以用EK算法代替跑最大流。(dinic弧优化也可以过,但是比较慢)。
3.因为n的数量很大,所以从源点连的边数也很大,所以我们要尽量重用某些边,如果新加的边已经存在,直接把它的容量加上新边的容量就行,否则才新加边。
300ms+,EK算法:
#include<bits/stdc++.h>
#define INF INT_MAX/2
using namespace std;
const long long maxn=;
struct Edge
{
long long from,to,cap,flow;
Edge(long long u,long long v,long long c,long long f):from(u),to(v),cap(c),flow(f) {}
};
struct EdmondsKarp
{
vector<Edge> edges;
vector<long long> G[maxn];
long long a[maxn];
long long p[maxn];
long long m; void init(int n)
{
for(long long i=;i<=n;i++)
G[i].clear();
edges.clear();
m=;
} void AddEdge(long long from,long long to,long long cap)
{
edges.push_back(Edge(from,to,cap,));
edges.push_back(Edge(to,from,,));
G[from].push_back(m++);
G[to].push_back(m++);
} long long Maxflow(long long s,long long t)
{
long long flow=;
while(true)
{
memset(a,,sizeof(a));
queue<long long> Q;
Q.push(s);
a[s]=LLONG_MAX;
while(!Q.empty())
{
long long x=Q.front();
Q.pop();
for(long long i=;i<G[x].size();i++)
{
Edge& e = edges[G[x][i]];
if(!a[e.to]&&e.cap>e.flow)
{
p[e.to]=G[x][i];
a[e.to]=min(a[x],e.cap-e.flow);
Q.push(e.to);
}
}
if(a[t])
break;
}
if(!a[t])
break;
for(long long u=t;u!=s;u=edges[p[u]].from)
{
edges[p[u]].flow+=a[t];
edges[p[u]^].flow-=a[t];
}
flow+=a[t];
}
return flow;
}
}; EdmondsKarp anss; int x[],y[];
int vis[][]={};
int num_edg[][]; int main()
{
int n,S,T,cur_clk=; while(scanf("%d",&n)==)
{
if(n==)return ;
cur_clk++; int d;
scanf("%d",&d);
for(int i=;i<=n;i++)scanf("%d %d",&x[i],&y[i]); int num[][]={},Num=; for(int i=;i<=d;i++)
for(int j=i;j<=d;j++)
num[i][j]=++Num; S=++Num;
T=++Num; anss.init(Num); for(int i=;i<=d;i++)
for(int j=i;j<=d;j++)
for(int k1=i;k1<=j;k1++)
if(i!=j)
anss.AddEdge(num[i][j],num[k1][k1],INF); int ans[],sum_ans=;
int now_flow=; int now_edge=anss.m;
for(int i=;i<=d;i++)
anss.AddEdge(num[i][i],T,); for(int i=;i<=n;i++)
{
if(vis[x[i]][y[i]]!=cur_clk)
{
vis[x[i]][y[i]]=cur_clk;
anss.AddEdge(S,num[x[i]][y[i]],);
num_edg[x[i]][y[i]]=anss.m-;
}
else
anss.edges[num_edg[x[i]][y[i]]].cap++; now_flow+=anss.Maxflow(S,T);
if(now_flow!=i)
{
ans[sum_ans++]=i; for(int i=;i<*d;i+=)
anss.edges[now_edge+i].cap++;
}
} for(int i=;i<sum_ans;i++)printf("%d ",ans[i]);
printf("\n"); }
return ;
}
700ms+,Dinic算法
#include<bits/stdc++.h>
#define N 305
#define INF INT_MAX/2
using namespace std;
typedef struct
{
int v;
int flow;
}ss; ss edg[N*N];
int edges[N][N]; int now_edges=; void addedge(int u,int v,int flow)
{
edges[u][++edges[u][]]=now_edges;
edg[now_edges++]=(ss){v,flow};
edges[v][++edges[v][]]=now_edges;
edg[now_edges++]=(ss){u,};
} int dis[N],S,T;
int q[]; bool bfs()
{
memset(dis,,sizeof(dis));
int c1=,c2=;
q[]=S;
dis[S]=; while(c1<c2)
{
int now=q[c1];
c1++;
int Size=edges[now][]; for(int i=;i<=Size;i++)
{
ss e=edg[edges[now][i]];
if(e.flow>&&dis[e.v]==)
{
dis[e.v]=dis[now]+;
q[c2++]=e.v;
}
}
}
if(dis[T]==)return ;
return ; }
int current[N]; int dfs(int now,int maxflow)
{ if(now==T)return maxflow;
int Size=edges[now][]; for(int i=current[now];i<=Size;i++)
{
current[now]=i;
ss &e=edg[edges[now][i]]; if(e.flow>&&dis[e.v]==dis[now]+)
{
int Flow=dfs(e.v,min(maxflow,e.flow)); if(Flow)
{ e.flow-=Flow;
edg[edges[now][i]^].flow+=Flow;
return Flow;
}
}
}
return ;
} int dinic()
{
int ans=,flow;
while(bfs())
{
for(int i=;i<N;i++)current[i]=;
while(flow=dfs(S,INF))ans+=flow;
} return ans;
} void init(int n)
{
now_edges=;
for(int i=;i<=n;i++)edges[i][]=;
} int x[],y[];
int vis[][]={};
int num_edg[][]; int main()
{
int n,cur_clk=; while(scanf("%d",&n)==)
{
if(n==)return ;
cur_clk++; int d;
scanf("%d",&d);
for(int i=;i<=n;i++)scanf("%d %d",&x[i],&y[i]); int num[][]={},Num=; for(int i=;i<=d;i++)
for(int j=i;j<=d;j++)
num[i][j]=++Num; S=++Num;
T=++Num; init(Num); for(int i=;i<=d;i++)
for(int j=i;j<=d;j++)
for(int k1=i;k1<=j;k1++)
if(i!=j)
addedge(num[i][j],num[k1][k1],INF); int ans[],sum_ans=;
int now_flow=; int now_edge=now_edges;
for(int i=;i<=d;i++)
addedge(num[i][i],T,); for(int i=;i<=n;i++)
{
if(vis[x[i]][y[i]]!=cur_clk)
{
vis[x[i]][y[i]]=cur_clk;
num_edg[x[i]][y[i]]=now_edges;
addedge(S,num[x[i]][y[i]],);
}
else
edg[num_edg[x[i]][y[i]]].flow++; now_flow+=dinic();
if(now_flow!=i)
{
ans[sum_ans++]=i; for(int i=;i<*d;i+=)
edg[now_edge+i].flow++;
}
} for(int i=;i<sum_ans;i++)printf("%d ",ans[i]);
printf("\n"); }
return ;
}
Annual Congress of MUD的更多相关文章
- Annual Congress of MUD(最大流)
Annual Congress of MUD 时间限制: 1 Sec 内存限制: 128 MB提交: 80 解决: 10[提交] [状态] [讨论版] [命题人:admin] 题目描述 Multi ...
- 穿越泥地(mud) (BFS)
问题 C: 穿越泥地(mud) 时间限制: 1 Sec 内存限制: 128 MB提交: 16 解决: 10[提交][状态][讨论版] 题目描述 清早6:00,FJ就离开了他的屋子,开始了他的例行工 ...
- MUD江湖_MUD文字游戏_MUD五指_武林群侠_北侠_夺宝江湖_书剑_文字江湖游戏_MUD游戏下载
MUD江湖_MUD文字游戏_MUD五指_武林群侠_北侠_夺宝江湖_书剑_文字江湖游戏_MUD游戏下载 武侠类手机文字游戏,经典再现高度自由玩法宠物 自制装备 师徒自立门派 自造武功欢迎来玩 Q群 1 ...
- 收MUD巫师学徒,MUD开发,LPC语言开发
收MUD巫师学徒,MUD开发,LPC语言开发 对这个有兴趣的联系我,签订协议 Q 184377367
- 【转】MUD教程--巫师入门教程4
我们再次复习一下clean_up()函数返回1的含义,如果clean_up()函数返回1,则MUDOS在这一次的调用时不会做其的任何举动,但到了下一次想调用的时间里,还将再次调用这个对象的clean_ ...
- MUD教程--巫师入门教程3
1. 指令格式为:edit <档名>,只加文件名,默认为当前目录,加here,表示编辑你当前所处的房间, 回车后即进入线上编辑系统. 2. 如果这是一个已经有的档案,你可以使用 z 或 Z ...
- 【转】MUD教程--巫师入门教程2
简单的人物原则上只要有 set_name<名字> . combat_exp <经验>就行了,当然我们总得稍微多添一点了.inherit NPC;void create(){ s ...
- 【转】MUD教程--巫师入门教程1
<新巫师入门手册> 第一章:观念篇■ 内容提要:什么是巫师?怎样做一个巫师?如何做好一个巫师? 第二章:上手篇■ 内容提要:最简单的房间怎么写?NPC又怎么写?先看懂一些常用的参数? 第三 ...
- mud目录命令说明
目錄結構 以下列出的是 ES2 mudlib 根目錄下標準的子目錄結構,以及簡短的說明. /adm 儲存由系統管理者所管理的程式與資料檔. /std 儲存標準物件的程式碼. /obj 儲存通用物件 ...
随机推荐
- SQLite基础教程目录
SQLite基础教程目录 SQLite主页 SQLite概述 SQLite -安装 SQLite -命令 SQLite -语法 SQLite -数据类型 SQLite -创建数据库 SQLite -附 ...
- SQL——SQL语言全部关键字详解
http://blog.csdn.net/quinnnorris/article/details/71056445 数据库中我们做常用的就是SQL基本查询语言,甚至有些人认为数据库就是SQL,SQL就 ...
- Xcode编译工具
一.关于Other Linker Flags xcode中,在“Targets”选项下有Other Linker Flags选项,在这里可以填写xcode链接器的参数,如:-ObjC.-all_loa ...
- CAD交互绘制块引用对象(网页版)
主要用到函数说明: _DMxDrawX::DrawBlockReference 绘制块引用对象.详细说明如下: 参数 说明 DOUBLE dPosX 插入点的X坐标 DOUBLE dPosY 插入点的 ...
- pytorch中的view
https://ptorch.com/news/59.html view()相当于reshape(),其中参数若为-1表示当前的size根据其余size推断
- xampp中php手动升级
http://windows.php.net/download/ //要下载的 里面有dll文件 http://www.php.net/downloads.php VC9 x86 ...
- C++的反射
写得挺不错,支持转帖下 C++语言本身是不支持反射的,但实际应用中总是会有将对象序列化的需求,总不可能C++不支持,我们就不用C++了,既然发明C++的大师们没有考虑这个,那我们只有自己动手了,毛主席 ...
- C语言数组_04
概念:数组是在程序设计中,为了处理方便, 把具有相同类型的若干变量按有序的形式组织起来的一种形式.这些按序排列的同类数据元素的集合称为数组.在C语言中,数组属于构造数据类型.一个数组可以分解为多个数组 ...
- [九省联考2018] IIIDX 线段树+贪心
题目: 给出 k 和 n 个数,构造一个序列使得 d[i]>=d[i/k] ,并且字典序最大. 分析: 听说,当年省选的时候,这道题挡住了大批的高手,看上去十分简单,实际上那道弯段时间内是转不过 ...
- 组合的输出(DFS)
题目描述: 排列与组合是常用的数学方法,其中组合就是从n个元素中抽出r个元素(不分顺序且r<=n),我们可以简单地将n个元素理解为自然数1,2,…,n,从中任取r个数. 现要求你用递归的方法输出 ...