uvalive 3231 Fair Share 公平分配問題 二分+最大流 右邊最多流量的結點流量盡量少。
阿新 • • 發佈:2017-07-22
init targe memset save amp class tps blog ext
/** 題目: uvalive 3231 Fair Share 公平分配問題 鏈接:https://vjudge.net/problem/UVALive-3231 題意:有m個任務,n個處理器,每個任務有兩個候選處理器,只要其中一個運行,該任務就能執行。 不同任務的兩個候選處理器,至少有一個不同。 求任務數最多的那個處理器所分配的任務數盡量少。 思路:二分+最大流 左邊是任務,s->u,cap = 1。 如果任務u和u的候選處理器v,u->v, cap = 1. 右邊是處理器,二分mi。所有處理器v,v->t, cap = mi; 求s-t最大流flow,如果flow等於任務數,那麽可行解。找一個最小的mi即可。*/ #include<iostream> #include<cstring> #include<vector> #include<map> #include<cstdio> #include<sstream> #include<algorithm> #include<queue> using namespace std; typedef long long LL; const int INF = 0x3f3f3f3f; typedef long long LL; const int N = 11010;///n+m=1000+10000=11000; struct Edge{ int from, to, cap, flow; Edge(int u,int v,int c,int f):from(u),to(v),cap(c),flow(f){} }; struct Dinic{ int n, m, s, t; vector<Edge> edges; vector<int> G[N]; bool vis[N]; int d[N]; int cur[N]; void init(int n) { this->n = n; for(int i = 0; i <= n; i++) G[i].clear(); edges.clear(); } void AddEdge(int from,int to,int cap) { edges.push_back(Edge(from,to,cap,0)); edges.push_back(Edge(to,from,0,0)); 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); d[s] = 0; vis[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){ vis[e.to] = 1; d[e.to] = d[x]+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(d[x]+1==d[e.to]&&(f=DFS(e.to,min(a,e.cap-e.flow)))>0){ e.flow += f; edges[G[x][i]^1].flow -= f; flow += f; a -= f; if(a==0) break; } } return flow; } int Maxflow(int s,int t){ this->s = s, this->t = t; int flow = 0; while(BFS()){ memset(cur, 0, sizeof cur); flow += DFS(s,INF); } return flow; } }; int main() { int T, n, m; cin>>T; while(T--) { scanf("%d%d",&n,&m); int s = 0, t = n+m+1; Dinic dinic, save; dinic.init(t); int u , v; for(int i = 1; i <= m; i++){ scanf("%d%d",&u,&v); dinic.AddEdge(s,i,1); dinic.AddEdge(i,u+m,1); dinic.AddEdge(i,v+m,1); } save = dinic; int lo = 0, hi = INF, mi, ans; while(lo<=hi){ mi = (lo+hi)/2; dinic = save; for(int i = 1; i <= n; i++){ dinic.AddEdge(i+m,t,mi); } int flow = dinic.Maxflow(s,t); if(flow==m){ ans = mi; hi = mi-1; }else { lo = mi+1; } } printf("%d\n",ans); } return 0; }
uvalive 3231 Fair Share 公平分配問題 二分+最大流 右邊最多流量的結點流量盡量少。