PAT TOP 1021. Safe Fruit (35)

问题描述:

1021. Safe Fruit (35)

时间限制
1500 ms
内存限制
65536 kB
代码长度限制
8000 B
判题程序
Standard
作者
CHEN, Yue

There are a lot of tips telling us that some fruits must not be eaten with some other fruits, or we might get ourselves in serious trouble. For example, bananas can not be eaten with cantaloupe (哈密瓜), otherwise it will lead to kidney deficiency (肾虚).

Now you are given a long list of such tips, and a big basket of fruits. You are supposed to pick up those fruits so that it is safe to eat any of them.

Input Specification:

Each input file contains one test case. For each case, the first line gives two positive integers: N, the number of tips, and M, the number of fruits in the basket. both numbers are no more than 100.

Then two blocks follow. The first block contains N pairs of fruits which must not be eaten together, each pair occupies a line and there is no duplicated tips; and the second one contains M fruits together with their prices, again each pair in a line. To make it simple, each fruit is represented by a 3-digit ID number. A price is a positive integer which is no more than 1000. All the numbers in a line are separated by spaces.

Output Specification:

For each case, first print in a line the maximum number of safe fruits. Then in the next line list all the safe fruits, in increasing order of their ID's. The ID's must be separated by exactly one space, and there must be no extra space at the end of the line. Finally in the third line print the total price of the above fruits. Since there may be many different solutions, you are supposed to output the one with a maximum number of safe fruits. In case there is a tie, output the one with the lowest total price. It is guaranteed that such a solution is unique.

Sample Input:
16 20
001 002
003 004
004 005
005 006
006 007
007 008
008 003
009 010
009 011
009 012
009 013
010 014
011 015
012 016
012 017
013 018
020 99
019 99
018 4
017 2
016 3
015 6
014 5
013 1
012 1
011 1
010 1
009 10
008 1
007 2
006 5
005 3
004 4
003 6
002 1
001 2
Sample Output:
12
002 004 006 008 009 014 015 016 017 018 019 020
239

直接dfs+剪枝就行了,顺便感谢一下 dalao给出的关于”dp[i]数组保存编号为i的水果后能得到的的最大水果个数“的剪枝思路http://blog.csdn.net/bendaai

(第一次写blog,有点方)

ac代码:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#include<bits/stdc++.h>
using namespace std;
struct node
{
	set<int> s;
	int p;
	int dp;
	bool v;
} no;

map<int,node> m;
vector<set<int> > v;
vector<int> vb,vr,vn;
int mnum,msum;

void dfs(set<int>::iterator its,int num,int sum,int vi,int vj)
{
	if(its==v[vi].end())
	{
		if(num>mnum||(num==mnum&&sum<msum))
		{
			vr=vb;
			mnum=num;
			msum=sum;
		}
		return;
	}
	else if(num+v[vi].size()-vj<mnum)
	return;
	else if(num+m[*its].dp<mnum&&m[*its].dp>0)
	return;
	else
	{
		int kk,k=*its;
		if(!vb.empty())
		kk=vb.back();
		
		if(!m[k].v)
		{
			set<int>::iterator itss;

			vector<int> vl;
			for(itss=m[k].s.begin();itss!=m[k].s.end();++itss)
			if(!m[*itss].v)
			{
				m[*itss].v=true;
				vl.push_back(*itss);
			}

			vb.push_back(k);
			++its;
			dfs(its,num+1,sum+m[k].p,vi,vj+1);
			--its;

			if(vb.size()>1)
			{
				if(m[k].dp+1>m[kk].dp)
				m[kk].dp=m[k].dp+1;
			}

			vb.pop_back();			
			for(int i=0;i<vl.size();i++)
			m[vl[i]].v=false;
		}
		++its;
		dfs(its,num,sum,vi,vj+1);
		--its;
		
		if(vb.size()>1)
		{
			if(m[k].dp+1>m[kk].dp)
			m[kk].dp=m[k].dp+1;
		}
	}
}

void bfs()
{
	queue<int> q;
	map<int,node>::iterator itm;
	set<int>::iterator its;
	for(itm=m.begin();itm!=m.end();++itm)
	{
		if((itm->second).v)
		{
			(itm->second).v=false;
			int vs=v.size();
			set<int> sv;
			v.push_back(sv);
			v[vs].insert(itm->first);
			
					
			q.push(itm->first);
			for(;!q.empty();q.pop())
			{
				int k=q.front();
				for(its=m[k].s.begin();its!=m[k].s.end();++its)
				{
					if(m[*its].v)
					{
						m[*its].v=false;
						v[vs].insert(*its);
						q.push(*its);
					}
				}
			}
		}
	}
}

int main()
{
//    ios::sync_with_stdio(false);
//	freopen("data.txt","r",stdin);
	int n,k,c1,c2,x,p1,p2,c=0,t=0;
	scanf("%d %d",&n,&k);
	mnum=0,msum=0;
	for(;n--;)
	{
		scanf("%d %d",&c1,&c2);
		m[c1].s.insert(c2);
		m[c2].s.insert(c1);		
	}
	for(;k--;)
	{
		scanf("%d %d",&c1,&c2);
		m[c1].p=c2;
		m[c1].v=true;
		m[c1].dp=0;
	}
	
	bfs();
	
	int mmn=0,mms=0;
	for(int i=0;i<v.size();i++)
	{
		mnum=0,msum=0;
		dfs(v[i].begin(),0,0,i,0);
		mmn+=mnum;
		mms+=msum;
		for(int i=0;i<vr.size();i++)
		vn.push_back(vr[i]);
	}
	sort(vn.begin(),vn.end());
	printf("%d\n%03d",mmn,vn[0]);
	for(int i=1;i<vn.size();i++)
	printf(" %03d",vn[i]);
	printf("\n%d",mms);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值