poj3342
View Code
1 #include <map> 2 #include <stdio.h> 3 #include <vector> 4 #include <string> 5 #include <iostream> 6 using namespace std; 7 const int N=205; 8 vector<int > V[N]; 9 map<string,int> M; 10 string child,father; 11 int dp[N][2]; 12 bool ok[N][2]; 13 int n,cnt; 14 void init(){ 15 M.clear(); 16 cnt=0; 17 for(int i=1;i<=n;i++){ 18 V[i].clear(); 19 dp[i][0]=0; 20 dp[i][1]=1; 21 ok[i][0]=ok[i][1]=1; 22 } 23 } 24 void input(){ 25 cin>>father; 26 M[father]=++cnt; 27 for(int i=1;i<n;i++){ 28 cin>>child; 29 if(M[child]==0){ 30 M[child]=++cnt; 31 } 32 cin>>father; 33 if(M[father]==0){ 34 M[father]=++cnt; 35 } 36 V[M[father]].push_back(M[child]); 37 } 38 } 39 //dp[i][0] = ∑max(dp[j][0], dp[j][1]) (j是i的儿子) 40 //dp[i][1] = 1 + ∑dp[j][0] (j是i的儿子) 41 void dfs(int u){ 42 int i,v; 43 for(i=0;i<V[u].size();i++){ 44 int v=V[u][i]; 45 dfs(v); 46 dp[u][1]+=dp[v][0]; 47 if(ok[v][0]==0) ok[u][1]=0; 48 if(dp[v][0]==dp[v][1]){ 49 dp[u][0]+=dp[v][0]; 50 ok[u][0]=0; 51 }else if(dp[v][0]>dp[v][1]){ 52 dp[u][0]+=dp[v][0]; 53 if(ok[v][0]==0) ok[u][0]=0; 54 }else if(dp[v][0]<dp[v][1]){ 55 dp[u][0]+=dp[v][1]; 56 if(ok[v][1]==0) ok[u][0]=0; 57 } 58 } 59 return ; 60 } 61 void solve(){ 62 dfs(1); 63 if(dp[1][1]==dp[1][0]){ 64 printf("%d No\n",dp[1][1]); 65 }else if(dp[1][1]>dp[1][0]){ 66 printf("%d ",dp[1][1]); 67 if(ok[1][1]) puts("Yes"); 68 else puts("No"); 69 }else{ 70 printf("%d ",dp[1][0]); 71 if(ok[1][0]) puts("Yes"); 72 else puts("No"); 73 } 74 } 75 int main(){ 76 while(cin>>n&&n){ 77 init(); 78 input(); 79 solve(); 80 } 81 return 0; 82 }
poj1463
一开始理解成为只能在边上监视了,写好代码才意识到是点上监视,不过可以练习一下边上监视~
View Code
1 #include <stdio.h> 2 #include <vector> 3 #include <string> 4 #include <iostream> 5 using namespace std; 6 const int N=1505; 7 bool in[N]; 8 int dp[N][2]; 9 int n,m,a,b; 10 vector<int> V[N]; 11 int min(int a,int b){ 12 return a<b?a:b; 13 } 14 void init(){ 15 for(int i=0;i<n;i++){ 16 V[i].clear(); 17 in[i]=1; 18 dp[i][0]=0; 19 dp[i][1]=1; 20 } 21 } 22 /* 23 如果父节点无人看守,则孩子节点必须有人看守 24 如果父节点有人看守,则孩子节点可以有人看守也可以无人看守 25 */ 26 void dfs(int u){ 27 for(int i=0;i<V[u].size();i++){ 28 int v=V[u][i]; 29 dfs(v); 30 dp[u][1]+=min(dp[v][0],dp[v][1]); 31 dp[u][0]+=dp[v][1]; 32 } 33 return ; 34 } 35 int main(){ 36 int i; 37 while(scanf("%d",&n)!=EOF){ 38 init(); 39 for(i=0;i<n;i++){ 40 scanf("%d:(%d)",&a,&m); 41 for(int j=0;j<m;j++){ 42 scanf("%d",&b); 43 in[b]=0; 44 V[a].push_back(b); 45 } 46 } 47 for(i=0;i<n;i++){ 48 if(in[i]){ 49 dfs(i); 50 break; 51 } 52 } 53 printf("%d\n",min(dp[i][0],dp[i][1])); 54 } 55 return 0; 56 }
poj3345
题意:有n个国家,要求至少买通m个,求最小代价,其中如果买通了一个国家,那么从属于它的国家也就视为被买通了,这些国家间的关系是一棵树。
思路:dp[i][j]表示以i为根的树中j个点花费的总价钱。
dp[root][k] = min(dp[root][k],dp[child][j]+dp[root][k-j]);
dp[root][num[root]] = weight[root];
View Code
1 #include<iostream> 2 #include<string> 3 #include<map> 4 #include<vector> 5 #include<stdio.h> 6 using namespace std; 7 #define inf 0x3f3f3f3f 8 #define N 205 9 char str[N*100]; 10 char ch[N]; 11 int num[N],w[N]; 12 bool in[N]; 13 vector<int>V[N]; 14 int dp[N][N]; 15 int min(int a,int b){ 16 return a<b?a:b; 17 } 18 int n,m; 19 void dfs(int u){ 20 int i,j,k,v; 21 num[u]=1; 22 dp[u][0]=0; 23 for(i=0;i<V[u].size();i++){ 24 v=V[u][i]; 25 dfs(v); 26 num[u]+=num[v]; 27 for(k=num[u];k>=0;k--){ 28 for(j=1;j<=k;j++) 29 dp[u][k]=min(dp[u][k],dp[v][j]+dp[u][k-j]); 30 } 31 } 32 dp[u][num[u]]=w[u]; 33 return ; 34 } 35 bool check(char c){ 36 if(c>='0'&&c<='9') return 1; 37 return 0; 38 } 39 int main(){ 40 int i,j,cnt,v; 41 while(gets(ch)!=NULL){ 42 if(ch[0]=='#') break; 43 //input 44 map<string,int>M; 45 46 cnt=v=0; 47 for(i=0;check(ch[i]);i++){ 48 v=v*10+ch[i]-'0'; 49 } 50 n=v; 51 52 v=0; 53 for(i++;check(ch[i]);i++){ 54 v=v*10+ch[i]-'0'; 55 } 56 m=v; 57 58 w[0]=0; 59 for(i=0;i<=n;i++){ 60 V[i].clear(); 61 in[i]=1; 62 } 63 64 for(i=0;i<n;i++){ 65 gets(str); 66 for(j=0;str[j]!=' ';j++); 67 str[j]='\0'; 68 if(M[str]==0) M[str]=++cnt; 69 70 v=0; 71 for(j++;check(str[j]);j++){ 72 v=v*10+str[j]-'0'; 73 } 74 w[M[str]]=v;//!!!!!!!WA is w[cnt]=v; 75 76 while(str[j]!='\0'){ 77 int top=0; 78 for(j++;str[j]!='\0'&&str[j]!=' ';j++){ 79 ch[top++]=str[j]; 80 }ch[top]='\0'; 81 82 if(M[ch]==0) M[ch]=++cnt; 83 V[M[str]].push_back(M[ch]); 84 in[M[ch]]=0; 85 } 86 } 87 //solve 88 for(i=1;i<=n;i++){ 89 if(in[i]) 90 V[0].push_back(i); 91 } 92 for(i=0;i<=n;i++) 93 for(j=0;j<=n;j++) 94 dp[i][j]=inf; 95 dfs(0); 96 int ans=dp[0][m]; 97 for(i=m;i<=n;i++){ 98 if(dp[0][i]<ans) 99 ans=dp[0][i]; 100 } 101 printf("%d\n",ans); 102 } 103 return 0; 104 }