zoukankan      html  css  js  c++  java
  • Kos [最大流(TLE)]

    KosKos

    nn 个人,之间会有 mm 场比赛。你可以设定所有比赛的结果。你希望获胜场次最
    多的人获胜的场次数最少,问这个最小值是多少。

    1n1041 le n le 10^4, 0m1040 le m le 10^4 .


    color{red}{正解部分}

    最多的人获胜最少 ightarrow 二分答案 .

    二分答案得出 midmid, 然后 chkchk ,

    先建图 downarrow

    • s  (1)s ightarrow 比赛 (1)
    •   ()比赛 ightarrow 人 (-)
    • t (mid)人 ightarrow t (mid)

    然后检查最大流是否等于 MM, 即可 chkchk .


    color{red}{实现部分}

    重新跑 DinicDinic 需要注意以下内容

    • num0num0 的重置
    • haedhaed 的重置
    • MMNN 之间的区分 .

    重置时又需要注意点的范围为 [0,M+N]ft[0, M+N] ∪ f_t .

    #include<bits/stdc++.h>
    #define reg register
    
    const int maxn = 20004;
    const int inf = 0x3f3f3f3f;
    
    int N;
    int M;
    int Ans;
    int tim_reg;
    int f_s = 0;
    int f_t;
    int num0 = 1;
    int cur[maxn<<2];
    int dep[maxn<<2];
    int head[maxn<<2];
    int tmp_head[maxn<<2];
    
    struct Edge{ int nxt, to, w, flow; } edge[maxn << 3];
    
    void Add(int from, int to, int w, int flow = 0){
            edge[num0] = (Edge){ head[from], to, w, flow };
            head[from] = num0 ++;
    }
    
    bool BFS(){
    	for(reg int i = 0; i <= M+N; i ++) cur[i] = head[i];
    	cur[f_t] = head[f_t];
            memset(dep, 0, sizeof dep);
            std::queue <int> Q; Q.push(f_s);
    	dep[f_s] = 1; // !
            while(!Q.empty()){
                    int ft = Q.front(); Q.pop();
                    for(reg int i = head[ft]; ~i; i = edge[i].nxt){
                            int to = edge[i].to;
                            if(dep[to] || edge[i].flow >= edge[i].w) continue ;
                            dep[to] = dep[ft] + 1;
                            Q.push(to);
                            if(to == f_t) return 1;
                    }
            }
            return dep[f_t];
    }
    
    int DFS(int k, int Min_w){
            if(k == f_t) return Min_w;
            for(reg int &i = cur[k]; ~i; i = edge[i].nxt){
                    int to = edge[i].to, t = edge[i].w - edge[i].flow;
                    if(dep[to] != dep[k] + 1 || t <= 0) continue ;
                    int tmp = DFS(to, std::min(Min_w, t));
                    if(tmp){
                            edge[i].flow += tmp, edge[i^1].flow -= tmp;
                            return tmp;
                    }
            }
            return 0; // !
    }
    
    int Dinic(){
            int res = 0;
            for(reg int i = 0; i <= num0; i ++) edge[i].flow = 0;
            while(BFS()) res += DFS(f_s, inf);
            return res;
    }
    
    bool chk(int mid){
    	for(reg int i = 0; i <= M+N+1; i ++) head[i] = tmp_head[i];
            num0 = tim_reg;
            for(reg int i = 1; i <= N; i ++) Add(M+i, f_t, mid), Add(f_t, M+i, -mid);
            return Dinic() >= M;
    }
    
    int main(){
    	freopen("kos.in", "r", stdin);
    	freopen("kos.out", "w", stdout);
    	memset(head, -1, sizeof head);
    	scanf("%d%d", &N, &M);
    	for(reg int i = 1; i <= M; i ++){
                    Add(f_s, i, 1), Add(i, f_s, -1);
                    int a, b;
                    scanf("%d%d", &a, &b);
                    Add(i, M+a, inf), Add(M+a, i, -inf);
                    Add(i, M+b, inf), Add(M+b, i, -inf);
            }
            f_t = N+M+1;
            for(reg int i = 0; i <= M+N+1; i ++) tmp_head[i] = head[i];
            tim_reg = num0;  Ans = inf;
            
            int l = 1, r = M;
            while(l <= r){
                    int mid = l+r >> 1;
                    if(chk(mid)) Ans = std::min(Ans, mid), r = mid - 1;
                    else l = mid + 1;
            }
            printf("%d
    ", Ans);
    	return 0;
    }
    
    

    #include<bits/stdc++.h>
    using namespace std;
    const int N=4e4+5;
    const int M=2e6+5;
    const int inf=2147483647;
    int s,n,m,cnt,now=1,v[M],w[M],cr[N],nex[M],head[N],deep[N];
    void add(int x,int y,int z){
    	nex[++now]=head[x],w[now]=z;
    	head[x]=now,v[now]=y;
    }
    queue<int>que;
    struct each{
    	int x,y;
    }a[N];
    bool bfs(){
    	for(int i=0;i<=s;i++)	cr[i]=head[i];
    	for(int i=0;i<s;i++)	deep[i]=0;
    	que.push(s),deep[s]=1;
    	while(!que.empty()){
    		int x=que.front();que.pop();
    		for(int i=head[x];i;i=nex[i])
    			if(w[i]&&!deep[v[i]]){
    				deep[v[i]]=deep[x]+1;
    				que.push(v[i]);
    			}
    	}
    	return deep[0];
    }
    int dfs(int x,int f){
    	if(!x||!f)	return f;
    	int ans=0;
    	for(int &i=cr[x];i;i=nex[i])
    		if(w[i]&&deep[v[i]]==deep[x]+1){
    			int d=dfs(v[i],min(w[i],f));
    			if(!d)	continue;
    			w[i]-=d,ans+=d;
    			w[i^1]+=d,f-=d;
    			if(!f)	break;
    		}
    	if(!ans)	deep[x]=0;
    	return ans;
    }
    bool check(int x){
    	int ans=0;
    	now=1,cnt=n;
    	for(int i=0;i<=s;i++)	head[i]=0;
    	for(int i=1;i<=n;i++)	add(i,0,x),add(0,i,0);
    	for(int i=1;i<=m;i++){
    		++cnt,add(s,cnt,1),add(cnt,s,0);
    		add(cnt,a[i].x,1),add(a[i].x,cnt,0);
    		add(cnt,a[i].y,1),add(a[i].y,cnt,0);
    	}
    	while(bfs())
    	while(int d=dfs(s,inf))	ans+=d;
    	return ans==m;
    }
    int main(){
    	freopen("kos.in","r",stdin);
    	freopen("kos.out","w",stdout);
    	scanf("%d%d",&n,&m),s=n+m+1;
    	for(int i=1;i<=m;i++)
    		scanf("%d%d",&a[i].x,&a[i].y);
    	int l=1,r=m;
    	while(l<r){
    		int mid=l+r>>1;
    		if(check(mid))	r=mid;
    		else	l=++mid;
    	}
    	printf("%d
    ",l);
    	return 0;
    }
    
  • 相关阅读:
    129 01 Android 零基础入门 02 Java面向对象 06 Java单例模式 03 饿汉模式 VS 懒汉模式 02 懒汉式的代码实现
    128 01 Android 零基础入门 02 Java面向对象 06 Java单例模式 03 饿汉模式 VS 懒汉模式 01 饿汉式的代码实现
    127 01 Android 零基础入门 02 Java面向对象 06 Java单例模式 02 单例模式概述 01 单例模式的定义和作用
    126 01 Android 零基础入门 02 Java面向对象 06 Java单例模式 01 设计模式概述 01 设计模式简介
    125 01 Android 零基础入门 02 Java面向对象 05 Java继承(下)05 Java继承(下)总结 01 Java继承(下)知识点总结
    leetcode-----121. 买卖股票的最佳时机
    leetcode-----104. 二叉树的最大深度
    Json串的字段如果和类中字段不一致,如何映射、转换?
    Mybatis-Plus的Service方法使用 之 泛型方法default <V> List<V> listObjs(Function<? super Object, V> mapper)
    模糊查询
  • 原文地址:https://www.cnblogs.com/zbr162/p/11822529.html
Copyright © 2011-2022 走看看