zoukankan      html  css  js  c++  java
  • cable tv network

    题目要求 任意两个点不连通 这句话怎么有点熟悉?
    然后联想到最小割的定义:一个边集被删除以后S,T不再联通,则称该边集为网络的割。边的容量之和最小的割成为网络的最小割。
    emmm S,T 不再联通 确实有点像
    于是这道题就可以用网络流最大流来做!
    将一个点(x) 拆成 (x)(x+n) 在这之间连有向边流量为1
    对于原图中的无向边((x,y)),在网络中连接有向边((x',y),(y',x)),流量为inf
    这样我们就可以从原图点的集合中 枚举任意两个点作为S,T 然后跑网络流最大流即可 注意源点和汇点 他们的出点和入点的流量为inf 即((s,s+n),(t,t+n)) 这两条边的流量为inf
    细节详见代码

    #include <cstdio>
    #include <iostream>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    #include <cmath>
    using namespace std;
    const int maxn=1000;
    const int inf=1e9;
    int fir[maxn<<1],nxt[maxn<<1],to[maxn<<1],val[maxn<<1],mf,ans;
    int n,m,t,a[maxn],b[maxn],S,T,tot=1,dep[maxn],cnt[maxn],flag;
    int read(){
    	int x=0,f=1;char ch=getchar();
    	while(ch<'0' || ch>'9'){
    		if(ch=='-')	f=-1;
    		ch=getchar();
    	}
    	while(ch>='0' && ch<='9'){
    		x=x*10+ch-'0';
    		ch=getchar();
    	}
    	return x*f;
    }
    void add(int x,int y,int z){
    	nxt[++tot]=fir[x];fir[x]=tot;to[tot]=y;val[tot]=z;
    	nxt[++tot]=fir[y];fir[y]=tot;to[tot]=x;val[tot]=0;
    }
    void build_map(){
    	memset(fir,0,sizeof(fir));tot=1;
    	for(int i=1;i<=n;i++){
    		if(i==S || i==T) add(i,i+n,inf);
    		else add(i,i+n,1);	
    	}
    	for(int i=1;i<=m;i++)
    		add(a[i]+n,b[i],inf),add(b[i]+n,a[i],inf);
    }
    void bfs(){
    	memset(cnt,0,sizeof(cnt));
    	memset(dep,0xff,sizeof(dep));
    	queue<int> q;
    	q.push(T);dep[T]=0;cnt[dep[T]]++;
    	while(!q.empty()){
    		int x=q.front();q.pop();
    		for(int i=fir[x];i;i=nxt[i]){
    			int y=to[i];
    			if(dep[y]==-1){
    				dep[y]=dep[x]+1;
    				cnt[dep[y]]++;
    				q.push(y);
    			}
    		}
    	}
    }
    int dfs(int x,int flow){
    	if(x==T){
    		mf+=flow;return flow;
    	}
    	int f=0;
    	for(int i=fir[x];i;i=nxt[i]){
    		int y=to[i];
    		if(dep[y]==dep[x]-1 && val[i]){
    			int ff=dfs(y,min(flow-f,val[i]));
    			if(ff){
    				f+=ff;val[i]-=ff;val[i^1]+=ff;
    			}
    			if(f==flow)	return f;
    		}
    	}
    	if(!--cnt[dep[x]])	flag=1;
    	cnt[++dep[x]]++;
    	return f;
    }
    int main(){
    	scanf("%d",&t);
    	while(t--){
    		scanf("%d %d",&n,&m);ans=inf;
    		for(int i=1,x,y;i<=m;i++)
    			a[i]=read()+1,b[i]=read()+1;
    		for(int i=1;i<=n;i++){
    			for(int j=1;j<=n;j++){
    				if(i==j) continue;
    				S=i;T=j;mf=0;
    				build_map();
    				bfs();flag=0;
    				while(!flag)
    					dfs(S,inf);
    				ans=min(ans,mf);
    			}
    		}
    		if(n<=1 || ans==inf) printf("%d
    ",n);
    		else printf("%d
    ",ans);
    	}
    }
    
  • 相关阅读:
    有趣的面试题 11 单向链表
    CLR via C# 读书笔记 13 前台线程和后台线程
    c# 使用 new 操作符构造新对象中做了一些什么 (简单版)
    CLR via C# 读书笔记 11 何时使用线程或者线程池
    CLR via C# 读书笔记 31 一种单实例应用程序的实现(信号量)
    延时加载lazyload
    [评论]为什么中国的程序员技术偏低
    关于陈列设计和一些细节的体验
    滚动
    JavaScript 的 parseInt 取整
  • 原文地址:https://www.cnblogs.com/mendessy/p/11741068.html
Copyright © 2011-2022 走看看