題目
題意:你的手機通訊錄裡有n個聯絡人,m個分組,其中,有的聯絡人在多個分組裡。你的任務是重新規劃通訊錄,使得每個聯絡人只在乙個分組裡並且使人數最多的那個分組人數最少。找出人數最多的那個分組中的人數
分析:看到要求最大值的最小值(人數最多的那組的人數最少),很容易想到二分答案。
然後check就懵逼,自己一開始想什麼貪心亂搞,
然後看一下白書,又看看題解,臥槽最大流。
原諒我之前不會網路流,先看紫書,看到最後說效率不夠
再看藍書,dfs+bfs版本的dinic演算法,,,
分析的分析:二分人數最多的組的人數,以此為最大流量跑最大流,
增加節點:0=s,1~n為n個人,n+1~n+m為m個分組,n+m+1為t
從s向每乙個聯絡人連一條弧,容量為1,表示乙個聯絡人只能在乙個分組中;然後對於每個聯絡人向他所在的分組連一條弧,容量為1,表示在這個分組裡最多儲存一次該聯絡人;然後從每個分組向匯點連一條弧,容量為x,表示這個分組不能儲存超過x個聯絡人
如果最後每個點的流量都是1,表示每個人都走過了,return 1
廢話一大堆,主要記錄一下,最大流的模板
#include
#include
#include
#include
#include
#include
using
namespace
std;
const
int n=2333;
struct edge
};int s,t,n,m,top;
vector
edges;//0=s,1~n人,n+1~n+m組,n+m+1=t
vector
g[n];//鄰接表
vector
group[n];//記錄每個人屬於集合
bool vis[n];//use when bfs
int d[n],cur[n];//dist,now edge
void addedge(int from,int to,int cap)
bool bfs()
}return vis[t];
}int dfs(int x,int a)
return flow;
}int maxflow(int s,int t,int x)
return flow;
}bool check(int x)
}int flow=maxflow(s,t,x); //run
for (int i=0;iif (edges[g[s][i]].flow!=1)return
0; }
return1;}
int main()
}int l=0,r=n; //erfen
while (lif (l==r)break;
int mid=(l+r)>>1;
bool ok=check(mid);
if (ok) r=mid;
else l=mid+1;
}printf("%d\n",l);
}}
uva 12264 (Risk) 二分 最大流
題意 首先有n個點,然後每個點都乙個權值ai表示這個點上的士兵數量,如果ai為0則表示這個點是敵人的,如果大於零則表示這個點是自己的並且有ai個士兵,現在你只有一次機會可以移動所有的士兵,注意 每個士兵只能移動一次,並且只有兩種選擇,要麼不動,要麼移動到相鄰的乙個單位處的的自己的點上,並且自己的點在...
poj 2112 最大流 二分
題意 有k臺擠奶機,c頭奶牛,給出這k c個實體間的距離,求出每頭奶牛都到一台擠奶機去,怎麼分配使奶牛走的最大距離最小。用二分列舉最大距離,include include define n 500 define inf 0x3fffffff int map n n dis n gap n head ...
hdu 3228 最大流 二分
題意 一共有n個城市,一些城市裡有金礦,一些城市裡有倉庫,金礦和倉庫都有乙個容量,有m條邊,每條邊是雙向的,有乙個權值,求將所有金礦裡的儲量都運送到倉庫中,所需要經過的道路中,使最大的權值最小 思路 增設乙個超級源點和乙個超級匯點,源點與每乙個城市相連,容量為 數量,匯點與倉庫相連,容量為倉庫的容量...