• 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;
    }
    
  • 相关阅读:
    求随机数平均值方法 求随机数方差方法 求正态分布的随机数
    combox 绑定
    winform界面textbox框 鼠标经过时出现浮动
    Regex
    C# 3.0 一行求方差
    通过Linq 实现DataTable Group By
    ORACLE 时间运算
    发布几个国外的XHTML模板站,DIV+CSS模板下载
    C# 3.0新特性系列:隐含类型var
    在NTier 或多层应用程序中使用ADO.NET Entity Framework
  • 原文地址:https://www.cnblogs.com/zbr162/p/11822529.html
Copyright © 2020-2023  润新知