把給定的每種相同的時間段成一個點,再把每一天抽象成一個點,每一天都與匯點連一條容量爲0的邊(以後需要擴張,所以一開始設爲0)。
然後對於每個時間段,都對他對應的天連一條容量爲INF的邊。
然後這裏需要用到一個mp數組,用來存儲時間段對應的邊的序號,mp[x][y]即爲源點到 " 範圍爲x~y的區間代表的點 "的邊的序號。對於每個人建立區間的時候,先看他對應的區間有沒有被建立,如果沒有的話就建立這個區間,然後從源點到這個區間所代表的點連一條容量爲1的邊,在mp中記錄邊的序號。如果已經建立了,就爲源點到這個區間的邊容量+1(我們可以從mp中得到邊的序號)。隨後,跑一邊最大流,如果最大流小於當前的人數,則說明需要擴張”代表天的點到匯點“的邊的容量,所以我們打印出這個人的序號,然後爲”代表天的點到匯點“的邊容量+1(因爲我們最先連接的就是這些邊,所以他們的編號就是0~2*d,這裏要把反向邊算進去),然後繼續遍歷下一個點即可。
所以我們爲什麼要搞的這麼複雜呢?直接把每個人都設成一個點不行嗎?
這裏是考慮到時間複雜度,因爲最多有20天,所以最多隻有400個區間,而人數有10000個,這樣建圖可以極大的減少點的數量,加快速度。
#include <iostream>
#include <algorithm>
#include <string>
#include <stdio.h>
#include <cstdlib>
#include <math.h>
#include <cstring>
#include <iomanip>
#include <vector>
#include <queue>
using namespace std;
#define ll long long
#define N 1010
#define INF 0x3f3f3f3f
int mp[21][21];
int s,t;
struct Edge{
int from,to,cap,flow;
Edge(int a = 0,int b = 0,int c = 0,int d = 0){
from = a,to = b,cap = c,flow = d;
}
};
vector<Edge>edges;
vector<int>G[N];
bool vis[N];
int deep[N],cur[N];
void init(){
edges.clear();
for(int i=0;i<N;i++){
G[i].clear();
}
}
void guiling(){
int m = edges.size();
for(int i = 0 ;i<m;i++){
edges[i].flow = 0;
}
}
void addedges(int from,int to,int cap){
edges.push_back(Edge(from,to,cap,0));
edges.push_back(Edge(to,from,0,0));
int m = edges.size();
G[from].push_back(m-2);
G[to].push_back(m-1);
}
bool bfs(){
memset(vis,0,sizeof(vis));
queue<int>Q;
Q.push(s);
vis[s] = 1;deep[s] = 1;
while (!Q.empty())
{
int x = Q.front();Q.pop();
for(int i = 0 ;i < G[x].size(); i++){
Edge &e = edges[G[x][i]];
if(!vis[e.to] && e.cap > e.flow){
deep[e.to] = deep[x] + 1;
vis[e.to] = 1;
Q.push(e.to);
}
}
}
return vis[t];
}
int dfs(int x,int a){
if(x == t || a == 0){
return a;
}
int flow = 0,f;
for(int &i = cur[x];i<G[x].size();i++){
Edge &e = edges[G[x][i]];
if(deep[x] +1 == deep[e.to] && (f = dfs(e.to,min(e.cap - e.flow,a))) > 0){
e.flow += f;
edges[G[x][i]^1].flow -= f;
flow += f;
a -= f;
if(a == 0){
break;
}
}
}
return flow;
}
int MaxFlow(){
int flow = 0;
while (bfs())
{
memset(cur,0,sizeof(cur));
flow += dfs(s,INF);
}
return flow;
}
int n,d;
int main(){
int i,j,k,x,y;
//freopen("abc.txt","w",stdout);
while (scanf("%d",&n),n)
{
scanf("%d",&d);
init();
memset(mp,-1,sizeof(mp));
s = 0,t = 1000;
for(i=1;i<=d;i++){
addedges(i,t,0);
}
int cnt = d;//爲區域標號
vector<int>ans;
for(i=1;i<=n;i++){
scanf("%d%d",&x,&y);
if(mp[x][y] == -1){
cnt++;
addedges(s,cnt,1);
mp[x][y] = edges.size() - 2;//記錄下是哪兩條邊
for(j=x;j<=y;j++){
addedges(cnt,j,INF);
}
}else{
edges[mp[x][y]].cap++;
edges[mp[x][y]+1].cap++;
}
int p = MaxFlow();
guiling();
if(p < i){
for(j = 0;j< d * 2;j++){
edges[j].cap++;
}
ans.push_back(i);
}
}
for(i = 0;i< ans.size() - 1;i++){
printf("%d ",ans[i]);
}
printf("%d",ans[ans.size()-1]);
printf("\n");
}
return 0;
}