Time Limit: 1000MS | Memory Limit: 30000K | |
Total Submissions: 1081 | Accepted: 517 |
Description
Input
Output
Sample Input
5 2 1 2 1 2 3 2 3 4 2 4 5 1
Sample Output
6
题意:有n个地区,n-1条边,有两辆车在某一个地方,他们要从起点出发,清扫所有的街道,就是树上的边,求最小路径。
咋一看,没思路,只能往树的直径上想,直接拿所有边的二倍-直径也能ac,不过不明白原理,无法证明正确性。
代码:
/* *********************************************** Author :xianxingwuguan Created Time :2014-2-6 4:48:24 File Name :3.cpp ************************************************ */ #pragma comment(linker, "/STACK:102400000,102400000") #include <stdio.h> #include <iostream> #include <algorithm> #include <sstream> #include <stdlib.h> #include <string.h> #include <limits.h> #include <string> #include <time.h> #include <math.h> #include <queue> #include <stack> #include <set> #include <map> using namespace std; #define INF 0x3f3f3f3f #define eps 1e-8 #define pi acos(-1.0) typedef long long ll; const int maxn=100100; int head[maxn],dis[maxn],tol,n; struct node{ int next,to,val; node(){}; node(int _next,int _to,int _val):next(_next),to(_to),val(_val){} }edge[3*maxn]; void add(int u,int v,int val){ edge[tol]=node(head[u],v,val); head[u]=tol++; } int bfs(int &s){ memset(dis,-1,sizeof(dis)); dis[s]=0; queue<int> q; q.push(s); while(!q.empty()){ int u=q.front();q.pop(); for(int i=head[u];i!=-1;i=edge[i].next){ int v=edge[i].to; if(dis[v]!=-1)continue; dis[v]=dis[u]+edge[i].val; q.push(v); } } int mx=0; for(int i=1;i<=n;i++) if(dis[i]>mx)mx=dis[i],s=i; return mx; } int main() { //freopen("data.in","r",stdin); //freopen("data.out","w",stdout); int i,j,k,m,p; while(~scanf("%d%d",&n,&m)){ memset(head,-1,sizeof(head));tol=0; int sum=0; for(k=1;k<n;k++){ scanf("%d%d%d",&i,&j,&p); add(i,j,p); add(j,i,p); sum+=p; } int ans=bfs(m); ans=bfs(m); cout<<2*sum-ans<<endl; } return 0; }
下面是树形dp,dp[u][i]代表以u为根的子树有i辆车的代价,然后就是u与子节点背包跟新dp值的过程。
代码:
/* *********************************************** Author :xianxingwuguan Created Time :2014-2-6 5:53:24 File Name :3.cpp ************************************************ */ #pragma comment(linker, "/STACK:102400000,102400000") #include <stdio.h> #include <iostream> #include <algorithm> #include <sstream> #include <stdlib.h> #include <string.h> #include <limits.h> #include <string> #include <time.h> #include <math.h> #include <queue> #include <stack> #include <set> #include <map> using namespace std; #define INF 0x3f3f3f3f #define eps 1e-8 #define pi acos(-1.0) typedef long long ll; const int maxn=100100; int head[maxn],dp[maxn][3],tol; struct node{ int next,to,val; node(){}; node(int _next,int _to,int _val):next(_next),to(_to),val(_val){} }edge[3*maxn]; void add(int u,int v,int val){ edge[tol]=node(head[u],v,val); head[u]=tol++; } void dfs(int u,int fa){ for(int i=head[u];i!=-1;i=edge[i].next){ int v=edge[i].to; if(v==fa)continue; dfs(v,u); int ret[3]; for(int j=0;j<3;j++){ ret[j]=dp[u][j]; dp[u][j]=INF; } int tmp[3]={2*edge[i].val,edge[i].val,2*edge[i].val}; for(int j=2;j>=0;j--) for(int k=0;k<=j;k++) dp[u][j]=min(dp[u][j],ret[j-k]+dp[v][k]+tmp[k]); } } int main() { //freopen("data.in","r",stdin); //freopen("data.out","w",stdout); int i,j,k,m,n,p; while(~scanf("%d%d",&n,&m)){ memset(head,-1,sizeof(head)); tol=0; for(i=1;i<n;i++){ scanf("%d%d%d",&j,&k,&p); add(j,k,p); add(k,j,p); } memset(dp,0,sizeof(dp)); dfs(m,-1); int ans=INF; for(i=0;i<3;i++) ans=min(ans,dp[m][i]); cout<<ans<<endl; } return 0; }
原文:http://blog.csdn.net/xianxingwuguan1/article/details/18945567