• P2764 最小路径覆盖问题


    每个点至多被一条路径覆盖,考虑网络流中约束是边

    每个点拆成两个点 \((x, x')\) ,可以向自己连向的点做匹配 \((x' \to y)\),考虑一开始是 \(n\) 条路径,每匹配一个点就减少一条路径

    答案就是 \(n\) - 最大匹配数

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<queue>
    #include<vector>
    #include<cctype>
    #include<cstring>
    using namespace std;
    #define rg register
    inline int read(){
    	rg char ch=getchar();
    	rg int x=0,f=0;
    	while(!isdigit(ch)) f|=(ch=='-'),ch=getchar();
    	while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    	return f?-x:x;
    }
    int n,m;
    const int N=2005,M=6005<<2;
    int head[N],ver[M],nxt[M],flow[M],tot=1;
    int dis[N],cur[N];
    inline void add(int x,int y,int z){
    	ver[++tot]=y;
    	flow[tot]=z;
    	nxt[tot]=head[x];
    	head[x]=tot;
    }
    inline void adds(int x,int y,int z){
    	add(x,y,z);
    	add(y,x,0);
    }
    int s,t,vis[N];
    inline int bfs(){
    	queue<int> q;
    	q.push(s);
    	memset(dis,0,sizeof dis);
    	dis[s]=1;
    	while(!q.empty()){
    		int x=q.front();q.pop();
    		cur[x]=head[x];
    		for(int y,i=head[x];i;i=nxt[i]){
    			y=ver[i];
    			if(!dis[y]&&flow[i]){
    				dis[y]=dis[x]+1;
    				q.push(y);
    			}
    		}
    	}
    	return dis[t];
    }
    int dfs(int x,int f){
    	if(x==t) return f;
    	int used=0;
    	for(int y,w,&i=cur[x];i;i=nxt[i]){
    		y=ver[i];
    		if(dis[y]==dis[x]+1&&flow[i]){
    			w=dfs(y,min(f-used,flow[i]));
    			if(w){
    				flow[i]-=w;
    				flow[i^1]+=w;
    				used+=w;
    				if(used==f) return f;
    			}
    		}
    	}
    	if(!used) dis[x]=0;
    	return used;
    }
    inline int dinic(){
    	int ans=0;
    	while(bfs()) ans+=dfs(s,0x3f3f3f3f);
    	return ans;
    }
    void work(int x){
    	printf("%d ",x);
    	vis[x]=true;
    	for(int i=head[x];i;i=nxt[i]){
    		if(i&1||flow[i]) continue;
    		work(ver[i]-n);
    	}
    }
    signed main(){
    	n=read(),m=read();
    	s=0;t=n<<1|1;
    	for(int x,y,i=1;i<=m;++i){
    		x=read(),y=read();
    		adds(x,y+n,1);
    	}
    	for(int i=1;i<=n;++i) adds(s,i,1),adds(i+n,t,1);
    	int ans=n-dinic();
    	for(int i=1;i<=n;++i) if(!vis[i]) work(i),puts("");
    	printf("%d\n",ans);
    	return 0;
    }
    
  • 相关阅读:
    Spring、实例化Bean的三种方法
    Spring、编码剖析Spring管理Bean的原理
    Spring、Hello Spring
    Spring、控制反转与依赖注入(概念)
    Hibernate、批量操作数据
    Hibernate、3.6.7在线帮助文档
    Hibernate、乐观锁和悲观锁
    JQuery UI 精品UI推荐
    java 为pdf添加水印图片
    Hibernate 、继承关联映射
  • 原文地址:https://www.cnblogs.com/int256/p/13110348.html
Copyright © 2020-2023  润新知