zoukankan      html  css  js  c++  java
  • P2764 最小路径覆盖问题

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

    每个点拆成两个点 ((x, x')) ,可以向自己连向的点做匹配 ((x' o 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
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    MongoDB ODM
    MongoDb python连接
    json格式化
    IDEA使用
    centos7安装完mariadb设置初始密码
    linux虚机联网
    问题解决记录【612-714】
    资料积累
    技术名词理解
    eclipse
  • 原文地址:https://www.cnblogs.com/XiaoVsun/p/13110348.html
Copyright © 2011-2022 走看看