ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

最小不相交路径覆盖

2022-03-03 01:04:20  阅读:242  来源: 互联网

标签:10005 memset int 路径 最小 相交 vis sizeof 505


例1

hdoj 1151 air raid

有一张有向图,一些伞兵可以落在任意位置,沿着有向边往前走。注意一条路仅能被一个伞兵经过

问最少派出多少个伞兵

题解

这是一个最小(不相交)路径覆盖问题,因为从每个点出发,下一步最多经过一条边,因此可以用二分匹配解决(可以想见)

code

#include<bits/stdc++.h>   //二分匹配 
#define ll long long
using namespace std;
int n,m,p;
bool g[505][505],reserved[505];
int ans[505];

bool dfs(int now){
	for(int i=1;i<=n;i++){
		if(!reserved[i]&&g[now][i]){
			reserved[i]=1;
			if(ans[i]==-1||dfs(ans[i])){
				ans[i]=now;
				return 1;
			}
		}
	}
	return 0;
}

int main(){
	int t;cin>>t;
	while(t--){
		cin>>n>>m;
		
		memset(g,0,sizeof(g));
		memset(ans,-1,sizeof(ans));
		
		for(int i=1,x,y,z;i<=m;i++){
			scanf("%d%d",&x,&y);
			g[x][y]=1;
		}
		
		int anss=0;
		for(int i=1;i<=n;i++){
			memset(reserved,0,sizeof(reserved));
			if(dfs(i)) anss++;
		}
		
		cout<<n-anss<<endl;
	}
	return 0;
}

例2

hdoj 3861

缩点后,转化成最小路径覆盖问题

code

#include<bits/stdc++.h>   
#define ll long long      
using namespace std;
struct Edge{
	int to,nex;
}e[2][100005];
int head[2][10004],q[11005],f[11005],a[10005],va[10005],dp[10005];
int n,m,cnt[2],t;
bool vis[10005];
int x[100005],y[100005];
vector<int>v[10005];
int anss; 
int match[5005];  //下标是配对的b方  值为对应的a方 
bool reserve_b[5005];

void init(){
	memset(head,0,sizeof(head));
	memset(vis,0,sizeof(vis));
	memset(match,0,sizeof(match));
	for(int i=1;i<=n;i++)v[i].clear();  //
	t=0;
	cnt[0]=cnt[1]=0;
}

void add(int u,int v){
	cnt[0]++;
	e[0][cnt[0]].to=v;
	e[0][cnt[0]].nex=head[0][u];
	head[0][u]=cnt[0];
}

void add2(int u,int v){
	cnt[1]++;
	e[1][cnt[1]].to=v;
	e[1][cnt[1]].nex=head[1][u];
	head[1][u]=cnt[1];
}

void dfs1(int now){
	vis[now]=1;
	for(int i=head[0][now];i;i=e[0][i].nex){
		int x=e[0][i].to;
		if(!vis[x]) dfs1(x);
	}
	q[++t]=now;
}

void dfs2(int now,int y){
	vis[now]=0;  f[now]=y;
	for(int i=head[1][now];i;i=e[1][i].nex){
		int x=e[1][i].to;
		if(vis[x]) dfs2(x,y);
	}
}

//二分图匹配  
bool dfs(int now){
	for(int i=0;i<v[now].size();i++){
		int x=v[now][i];
		if(!reserve_b[x]){
			reserve_b[x]=1;
			if(!match[x]||dfs(match[x])){  //b无配对 或者 b的原配可以找到新的配对 
				match[x]=now;  //则令x为b的配对 
				return 1;  //x找到了配对 
			}
		}
	}
	return 0;
}

int main(){
	int T;cin>>T; 
	while(T--){
		cin>>n>>m;
		init();
		for(int i=1;i<=m;i++){
			scanf("%d%d",&x[i],&y[i]);
			add(x[i],y[i]);
			add2(y[i],x[i]);
		}
		for(int i=1;i<=n;i++){
			if(!vis[i]){
				dfs1(i);
			}
		}
		for(int i=n;i>=1;i--){
			if(vis[q[i]]){
				dfs2(q[i],q[i]);
			}
		}
		
		
		for(int i=1;i<=m;i++){
			if(f[x[i]]!=f[y[i]]) v[f[x[i]]].push_back(f[y[i]]);
		}
		set<int>st;
		for(int i=1;i<=n;i++){
			st.insert(f[i]);
			va[f[i]]+=a[i];
		}
		
		anss=0;
		for(auto i=st.begin();i!=st.end();i++){  //a方 
			memset(reserve_b,0,sizeof(reserve_b));  //不加会错
			if(dfs(*i)) anss++;  //ai配对成功后配对数++,虽然可能更换配对,但是保证ai一定有配对 
		}
		cout<<st.size()-anss<<endl;
	} 
	
	return 0;
}

 

标签:10005,memset,int,路径,最小,相交,vis,sizeof,505
来源: https://www.cnblogs.com/re0acm/p/15957891.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有