现在的位置: 首页 > 综合 > 正文

poj3715——Blue and Red//最小顶点覆盖

2014年03月10日 ⁄ 综合 ⁄ 共 1096字 ⁄ 字号 评论关闭

看题的时候,看不出这是最小顶点覆盖,悲剧。

注意点:1,顶点从0开始,所以,my[]的标记不能以0为标准。

                2,枚举法确实很不错。

#include<iostream>
#include<string>
using namespace std;
int n,m;
int f[220];
class node
{
public:
	int to;
	int next;
};
int head[220],vis[220],my[220],del[220];
node e[20002];
int cnt;
void add(int a,int b)
{
	e[++cnt].to =b;
	e[cnt].next= head[a];
	head[a]=cnt;
}
bool dfs(int k)
{
	for(int u=head[k];u!=-1;u=e[u].next)
	{
		int v=e[u].to;
		if(!vis[v]&&!del[v])
		{
			vis[v]=1;
			if(my[v]==-1||dfs(my[v]))
			{
				my[v]=k;
				return true;
			}
		}
	}
	return false;
}
int  get()
{
	int now =0,i;
	memset(my,-1,sizeof(my));
	for(i=0;i<n;i++)
	{
		if(f[i]==0) continue;
		if(del[i]) continue;
		memset(vis,0,sizeof(vis));
		if(dfs(i))
			now++;
	}
	return now;
}
void solve()
{
	memset(del,0,sizeof(del));
	int sum =get(),now=sum,i;
	int ans[220],len=0;
	for(i=0;i<n;i++)
	{
		del[i]=1;
		bool flag=true;
		int k=get();
		if(k+1==now) 
		{
			now--;
			ans[len++]=i;
			flag=false;
		}
		if(flag)  del[i]=0;
	}
	cout<<sum<<" ";
	for(i=0;i<len;i++)
		cout<<ans[i]<<" ";
	cout<<endl;
}
void in()
{
	cin>>n>>m;
	for(int i=0;i<n;i++)
		{
			cin>>f[i];
			head[i]=-1;
		}
		for(int i=0;i<m;i++)
		{
			int a,b;
			cin>>a>>b;
			if(a==b) continue;
			if(f[a]==f[b]) continue;
			add(a,b);
			add(b,a);
		}
}
int main()
{
	int test;
	cin>>test;
	while(test--)
	{
		cnt=0;
		in();
		solve();
	}
	return 0;
}

抱歉!评论已关闭.