POJ3513 Let's Go to the Movies
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 1736 | Accepted: 429 |
Description
A favorite pastime for big families in Acmestan is going to the movies. It is quite common to see a number of these multi-generation families going together to watch a movie. Movie theaters in Acmestan have two types of tickets: A single ticket is for exactly one person while a family ticket allows a parent and their children to enter the theater. Needless to say, a family ticket is always priced higher than a single ticket, sometimes as high as five times the price of a single ticket.
It is quite challenging for families to decide which ticket arrangement is most economical to buy. For example, the family depicted in the figure on the right has four ticket arrangements to choose from: Seven single tickets; Two family tickets; One family ticket (for adam,bob, cindy) plus four single tickets for the rest; Or, one family ticket (for bob and his four children) plus single tickets for the remaining two.
Write a program to determine which ticket arrangement has the least price. If there are more than one such arrangement, print the arrangement that has the least number of tickets.
Input
Your program will be tested on one or more test cases. The first line of each test case includes two positive integers (S and F) where S is the price of a single ticket and F is the price of a family ticket. The remaining lines of the test case are either the name of a person going by him/herself, or of the form:
N1 N2 N3 … Nk
where N1 is the name of a parent, with N2… Nk being his/her children. Names are all lower-case letters, and no longer than 1000 characters. No parent will be taking more than 1000 of their children to the movies :-). Names are unique, the name of a particular person will appear at most twice: Once as a parent, and once as a child. There will be at least one person and at most 100,000 people in any test case.
The end of a test case is identified by the beginning of the following test case (a line made of two integers.) The end of the last test case is identified by two zeros.
Output
For each test case, write the result using the following format:
k. NS NF T
Where k is the test case number (starting at 1), NS is the number of single tickets, NF is the number of family tickets, and T is the total cost of tickets.
Sample Input
1 3 adam bob cindy bob dima edie fairuz gary 1 2 john paul george ringo 1 3 a b c 0 0
Sample Output
1. 2 1 5 2. 4 0 4 3. 0 1 3
Source
#include <stdio.h> #include <string> #include <string.h> #include <iostream> #include <vector> #include <map> #define N 100005 using namespace std; vector<long long>gra[N]; map<string,long long>hash; string nam; char str[1000*2000+5]; long long s,f,vis[N],id; struct Dp { long long ns,nf; }dp[N][2]; void dfs(long long r) { vis[r]=1; Dp temp; dp[r][1].nf=1; for(long long i=0;i<gra[r].size();i++) { long long t=gra[r][i]; dfs(t); long long a=s*dp[t][0].ns+f*dp[t][0].nf; long long b=s*dp[t][1].ns+f*dp[t][1].nf; if(a>b||(a==b&&dp[t][1].nf>dp[t][0].nf)) { dp[r][1].ns+=dp[t][1].ns; dp[r][1].nf+=dp[t][1].nf; } else { dp[r][1].ns+=dp[t][0].ns; dp[r][1].nf+=dp[t][0].nf; } dp[r][0].ns+=dp[t][1].ns; dp[r][0].nf+=dp[t][1].nf; } long long a=s*dp[r][0].ns+s+f*dp[r][0].nf; long long b=s*dp[r][1].ns+f*dp[r][1].nf; if(a<b||(a==b&&dp[r][0].nf>dp[r][1].nf)) { dp[r][1].ns=dp[r][0].ns+1; dp[r][1].nf=dp[r][0].nf; } } void run(long long h) { Dp ans; ans.nf=ans.ns=0; for(long long i=1;i<id;i++) if(vis[i]==0) { dfs(i); ans.nf+=dp[i][1].nf; ans.ns+=dp[i][1].ns; } printf("%lld. %lld %lld %lld\n",h,ans.ns,ans.nf,s*ans.ns+f*ans.nf); } int main() { gets(str); for(long long h=1;;h++) { sscanf(str,"%lld%lld",&s,&f); if(s==0&f==0)break; id=1; for(long long i=0;i<N;i++) gra[i].clear(); hash.clear(); memset(dp,0,sizeof(dp)); memset(vis,0,sizeof(vis)); while(1) { gets(str); if(str[0]>='0'&&str[0]<='9')break; if(!(str[0]>='a'&&str[0]<='z'))continue; long long flag=0,k=0,len=strlen(str),fa; char temp[1005]; for(long long i=0;i<=len;i++) { if(i==len||str[i]==' ') { temp[k]=0; k=0; nam=temp; if(hash.count(nam)==0)hash[nam]=id++; if(flag==0) flag=1,fa=hash[nam]; else gra[fa].push_back(hash[nam]),vis[hash[nam]]=1; continue; } temp[k++]=str[i]; } } run(h); } }